解决QSharedPointer栈变量的崩溃问题

发布于:2025-04-01 ⋅ 阅读:(23) ⋅ 点赞:(0)

参考

QSharedPointer的陷阱

qt中的共享指针,QSharedPointer类

崩溃

代码

#include <QtCore/QCoreApplication>
#include <QDebug>
#include <QSharedPointer>

class MyClass {
public:
	void doSomething() {
		qDebug() << __FUNCTION__;
	}
};
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

	{
		MyClass stackObj;          // 栈对象,生命周期由作用域管理
		QSharedPointer<MyClass> ptr(&stackObj); // 错误!QSharedPointer 会尝试 delete 栈对象
		ptr->doSomething();
	}
	
    return a.exec();
}

现象

  1. Qt\5.15.2\msvc2019_64\include\QtCore\qsharedpointer_impl.h
    析构
    1
    2外部部引用计数数据
    3
    外部部引用计数数据的删除器
    在这里插入图片描述
    自定义删除器
    在这里插入图片描述

  2. C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.41.34120\crt\src\vcruntime\delete_scalar_size.cpp
    在这里插入图片描述

  3. C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.41.34120\crt\src\vcruntime\delete_scalar.cpp

解决

  • 特殊情况:自定义删除器(非栈对象)
    如果确实需要管理非 new 创建的资源,可以通过自定义删除器避免 delete
QSharedPointer<MyClass> ptr(&stackObj, [](MyClass*) {
    // 空删除器,不执行 delete
});

但这种情况极少见,且需确保栈对象的生命周期长于 QSharedPointer

#include <QtCore/QCoreApplication>
#include <QDebug>
#include <QSharedPointer>

class MyClass {
public:
	void doSomething() {
		qDebug() << __FUNCTION__;
	}
};
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

	{
#if 1
		MyClass stackObj;						// 栈对象,生命周期由作用域管理
#if 0
		QSharedPointer<MyClass> ptr(&stackObj); // 错误!QSharedPointer 会尝试 delete 栈对象
#else
		QSharedPointer<MyClass> ptr(&stackObj, [](auto*) {
			// 空删除器,不执行 delete
	});
#endif
#else
		QSharedPointer<MyClass> ptr(new MyClass());// 正常
#endif

		ptr->doSomething();
	}
	
    return a.exec();
}