Ale*_*aev 8 c++ qt destructor pimpl-idiom qsharedpointer
昨天我遇到了痛苦,让我感到沮丧24小时.问题归结为随机发生的意外崩溃.更复杂的是,调试报告也具有绝对随机的模式.更复杂的是,所有调试跟踪都会导致随机 Qt源或本机DLL,即证明每次问题都不在我身边.
这里有几个这样可爱的报告的例子:
Program received signal SIGSEGV, Segmentation fault.
0x0000000077864324 in ntdll!RtlAppendStringToString () from C:\Windows\system32\ntdll.dll
(gdb) bt
#0 0x0000000077864324 in ntdll!RtlAppendStringToString () from C:\Windows\system32\ntdll.dll
#1 0x000000002efc0230 in ?? ()
#2 0x0000000002070005 in ?? ()
#3 0x000000002efc0000 in ?? ()
#4 0x000000007787969f in ntdll!RtlIsValidHandle () from C:\Windows\system32\ntdll.dll
#5 0x0000000000000000 in ?? ()
Run Code Online (Sandbox Code Playgroud)
warning: HEAP: Free Heap block 307e5950 modified at 307e59c0 after it was freed
Program received signal SIGTRAP, Trace/breakpoint trap.
0x00000000778bf0b2 in ntdll!ExpInterlockedPopEntrySListFault16 () from C:\Windows\system32\ntdll.dll
(gdb) bt
#0 0x00000000778bf0b2 in ntdll!ExpInterlockedPopEntrySListFault16 () from C:\Windows\system32\ntdll.dll
#1 0x000000007786fd34 in ntdll!RtlIsValidHandle () from C:\Windows\system32\ntdll.dll
#2 0x0000000077910d20 in ntdll!RtlGetLastNtStatus () from C:\Windows\system32\ntdll.dll
#3 0x00000000307e5950 in ?? ()
#4 0x00000000307e59c0 in ?? ()
#5 0x00000000ffffffff in ?? ()
#6 0x0000000000220f10 in ?? ()
#7 0x0000000077712d60 in WaitForMultipleObjectsEx () from C:\Windows\system32\kernel32.dll
#8 0x0000000000000000 in ?? ()
Run Code Online (Sandbox Code Playgroud)
Program received signal SIGSEGV, Segmentation fault.
0x0000000000a9678a in QBasicAtomicInt::ref (this=0x8) at ../../include/QtCore/../../../qt-src/src/corelib/arch/qatomic_x86_64.h:121
121 : "memory");
(gdb) bt
#0 0x0000000000a9678a in QBasicAtomicInt::ref (this=0x8) at ../../include/QtCore/../../../qt-src/src/corelib/arch/qatomic_x86_64.h:121
#1 0x00000000009df08e in QVariant::QVariant (this=0x21e4d0, p=...) at d:/Distributions/qt-src/src/corelib/kernel/qvariant.cpp:1426
#2 0x0000000000b4dde9 in QList<QVariant>::value (this=0x323bd480, i=1) at ../../include/QtCore/../../../qt-src/src/corelib/tools/qlist.h:666
#3 0x00000000009ccff7 in QObject::property (this=0x3067e900,
name=0xa9d042a <QCDEStyle::drawPrimitive(QStyle::PrimitiveElement, QStyleOption const*, QPainter*, QWidget const*) const::pts5+650> "_q_stylerect")
at d:/Distributions/qt-src/src/corelib/kernel/qobject.cpp:3742
#4 0x0000000000000000 in ?? ()
Run Code Online (Sandbox Code Playgroud)
你可以看到这些东西非常讨厌,它给了一个没有用的信息.但是,有一件事我没有注意.在编辑过程中这是一个奇怪的警告,这也很难被人注意:
In file included from d:/Libraries/x64/MinGW-w64/4.7.2/Qt/4.8.4/include/QtCore/qsharedpointer.h:50:0,
from d:/Libraries/x64/MinGW-w64/4.7.2/Qt/4.8.4/include/QtCore/QSharedPointer:1,
from ../../../../source/libraries/Project/sources/Method.hpp:4,
from ../../../../source/libraries/Project/sources/Slot.hpp:4,
from ../../../../source/libraries/Project/sources/Slot.cpp:1:
d:/Libraries/x64/MinGW-w64/4.7.2/Qt/4.8.4/include/QtCore/qsharedpointer_impl.h: In instantiation of 'static void QtSharedPointer::ExternalRefCount<T>::deref(QtSharedPointer::ExternalRefCount<T>::Data*, T*) [with T = Project::Method::Private; QtSharedPointer::ExternalRefCount<T>::Data = QtSharedPointer::ExternalRefCountData]':
d:/Libraries/x64/MinGW-w64/4.7.2/Qt/4.8.4/include/QtCore/qsharedpointer_impl.h:336:11: required from 'void QtSharedPointer::ExternalRefCount<T>::deref() [with T = Project::Method::Private]'
d:/Libraries/x64/MinGW-w64/4.7.2/Qt/4.8.4/include/QtCore/qsharedpointer_impl.h:401:38: required from 'QtSharedPointer::ExternalRefCount<T>::~ExternalRefCount() [with T = Project::Method::Private]'
d:/Libraries/x64/MinGW-w64/4.7.2/Qt/4.8.4/include/QtCore/qsharedpointer_impl.h:466:7: required from here
d:/Libraries/x64/MinGW-w64/4.7.2/Qt/4.8.4/include/QtCore/qsharedpointer_impl.h:342:21: warning: possible problem detected in invocation of delete operator: [enabled by default]
d:/Libraries/x64/MinGW-w64/4.7.2/Qt/4.8.4/include/QtCore/qsharedpointer_impl.h:337:28: warning: 'value' has incomplete type [enabled by default]
Run Code Online (Sandbox Code Playgroud)
实际上,我只是作为最后的手段转向这个警告,因为在如此绝望的追求中找到一个错误,代码已经感染了字面意义上的死亡记录.
仔细阅读后,我回忆说,例如,如果一个人使用std::unique_ptr或者std::scoped_ptr用于Pimpl - 一个人当然应该提供析构函数,否则代码甚至不会编译.但是,我也记得std::shared_ptr不关心析构函数,没有它就可以正常工作.这是我不注意这个奇怪警告的另一个原因.长话短说,当我添加析构函数时,这个随机崩溃停止了.看起来Qt QSharedPointer有一些设计缺陷std::shared_ptr.我想如果Qt开发人员将此警告转换为错误会更好,因为调试这样的马拉松根本不值得花时间,精力和神经.
我的问题是:
QSharedPointer?为什么析构函数如此重要?QSharedPointer)是在堆栈上创建的,没有其他对象在死后可以访问它们.然而,在他们去世后的一段随机时间内发生了撞击.希望这些问题和我的帖子一般会帮助其他人避免过去24小时内我曾经去过的地狱.
小智 3
该问题已在 Qt 5 中得到解决,请参阅https://codereview.qt-project.org/#change,26974
编译器调用错误的析构函数或假设不同的内存布局可能会导致某种内存损坏。我想说编译器应该针对这个问题给出错误而不是警告。
| 归档时间: |
|
| 查看次数: |
1772 次 |
| 最近记录: |