使用QString会在QMap::remove之后导致崩溃
Using QString causes crash after QMap::remove
我有以下代码:
class NamedObjectContainer {
//...
QMap<QString, SomeStruct> mUsed;
//...
};
const StoredObject* NamedObjectContainer::use(const QString& name, const QString& userId)
{
qDebug()<<userId;
mUsed.remove(userId);
qDebug()<<userId;
//...
}
在这里,我试图通过键(userId)从QMap中删除元素。元素已正确移除。但令人惊讶的是,它在QMap::remove之后打印userId时崩溃了。
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb5b2c6c0 (LWP 24041)]
0xb5fe899c in memcpy () from /lib/i686/nosegneg/libc.so.6
(gdb) where
#0 0xb5fe899c in memcpy () from /lib/i686/nosegneg/libc.so.6
#1 0xb7263246 in QString::append () from /home/osmin/stand_cl_dir/Qt4_x86-linux/lib /libQtCore.so.4
#2 0xb72b6641 in ?? () from /home/osmin/stand_cl_dir/Qt4_x86-linux/lib/libQtCore.so.4
#3 0xb72b218b in QTextStream::operator<< () from /home/osmin/stand_cl_dir/Qt4_x86-linux/lib/libQtCore.so.4
#4 0xb6524740 in QDebug::operator<< () from /usr/lib/libqxmlrpc.so.1
#5 0xb62b5cc0 in tabexchange::NamedObjectContainer::use (this=0x9e2fb08, name=@0xbffe85e4, userId=@0xa12b780) at namedcontainer.cpp:208
是什么原因导致了问题?我使用的是Qt 4.4.3
要详细说明@TI的评论。。。
QString是一种隐式共享类型。每个由QString对象组成的新副本都会增加引擎盖下的引用计数,当计数为零时,它就会被销毁。
这里可能发生的情况是,有一个初始化例程生成了一个QString实例,将其作为密钥传递,映射生成了一份副本。(这不会复制数据,只是增加共享计数。)然后初始化例程销毁了它的实例,所以剩下的唯一共享实例是存储在映射中的共享计数为1的实例。
稍后,您可能会使用类似QMap::iterator::key()
的东西来获取映射中字符串键的const引用,作为userId
传入。这不会创建任何新的QString实例来添加到共享计数中,而是指向映射所拥有的实例。因此,当地图放开它时……它被破坏了,现在userId
是一个悬挂的引用。
(注意:你没有说明SomeStruct
中有什么。但如果通过它可以到达与密钥匹配的字符串的实例,该实例将在映射值的SomeStruct
被销毁时被销毁,那么传递对userId
这样的字符串的引用可能会导致类似的问题。)
隐式共享带来的一件事是,有时它会隐藏这种性质的bug——如果没有隐式共享,这些bug会变得更加明显。然而,它使解决方案"便宜":当您提取要传入的密钥时,将其复制到本地变量实例中。。。并将该变量对的const引用传递到此例程。这实际上不会复制数据,但会使userId
安全,因为还会有一个共享计数使其保持活动状态。
这有助于实现更普遍的好协议:将引用类型传递给例程应该意味着您可以保证被引用对象在所调用函数的整个运行时的生存期。如果有任何疑问,请制作一个副本并传递对副本的引用。
(注意:以后,尝试使用简单、自包含、正确的示例格式,包括添加和删除,这可以更容易地找到确凿的证据。没有它,我们只能对问题进行有根据的猜测……它可能完全是由程序中的其他原因引起的!)
- 当回溯以零开始时,如何调试崩溃
- 为什么在popback()操作之后,它仍然打印完整的矢量
- 内联映射初始化的动态atexit析构函数崩溃
- 执行函数时导致崩溃的变量
- 在类定义之后定义一个私有方法
- 程序崩溃并显示"std::out_of_range"错误
- 在循环C++中指定字符串之后,不会打印该字符串
- STD :: FSTREAM在使用预先分配的内存时在Main之后崩溃
- 在我关闭刚开始的孩子对话框并进入父母对话框之后,我的QT桌面应用程序不断崩溃
- 在析构函数之后打开新的QMainWindow崩溃
- p = new String [0]和p = new Int [0]之后,为什么当删除[] p时字符串版本崩溃
- 提出/输出文件,调用案例1之后的程序崩溃
- C++ 在阿托尔之后随机崩溃
- 使用QString会在QMap::remove之后导致崩溃
- C++,libxslt:在释放样式表之后释放样式表文档会导致崩溃
- 当shared_ptr超出范围时,c++崩溃..在成功运行至少100000次之后
- 在fork之后删除condition_variable时,boost崩溃
- 在 LockFileEx 之后调用 ReadFile 时崩溃
- 在 malloc 之后为数组赋值会导致崩溃
- 从函数崩溃返回,仅在代码中的某个点之后