【发布时间】:2012-12-29 17:23:55
【问题描述】:
我遇到了一个似乎很奇怪的问题,但这可能是 QMap 工作方式的一个怪癖,我只是不明白。很难总结问题,但我会尽力而为。
我有一个班级A,有一个QMap<QString, someType*> mySomeTypeMap;。当我在我的程序中加载一个新文件时,我想删除这个QMap 的所有内容,以便我可以用新数据重新填充它。我通过执行以下操作来做到这一点:
foreach (QString key, mySomeTypeMap.keys())
{
someType* toDelete = mySomeTypeMap.take(key);
//Show me the original address of the pointer
qDebug() << "toDelete: " << toDelete;
delete toDelete;
//Set the pointer to 0x0
toDelete = NULL;
}
qDebug() 语句打印出我要删除的值的正确地址,当我在调试器中查看toDelete 设置为NULL 后,它显示 0x0,这就是我想要的.
然后,在另一个类B 中,我有以下代码...
void B::setSomeType(someType* blah)
{
if (Blah != NULL)
{
//Calls a bunch of disconnect()'s
disconnectAllSignals();
Blah = blah;
//Calls a bunch of connect()'s
connectAllSignals();
}
}
现在,真正令人困惑的是我的程序在到达disconnectAllSignals(); 行时崩溃了。原因是它试图在Blah 上调用disconnect(),它已被删除,当我将其设置为NULL 时应该设置为0x0。但是,如果它实际上设置为NULL,它就永远不会进入该 if 块开始。在调试器中,我看到Blah 的地址与我在设置toDelete = NULL; 之前打印出qDebug() << "toDelete: " << toDelete; 时得到的地址完全相同。
TLDR;在我删除指针并将相同的指针设置为NULL 后,我不知道我的程序如何取回指针的原始地址。由于稍后在执行过程中指针未设置为NULL,因此会导致崩溃。
【问题讨论】:
-
第一个猜测:您没有遵循
someType的三法则。向我们展示someTye的定义。另外,mySomeTypeMap.take(key)返回原始元素的副本或指向元素本身的指针是什么? -
好吧,构造函数和析构函数都是空的……这是一个非常简单的数据类,不包含任何我需要清理的指针。我没有明确实现复制构造函数。无论如何,这将如何导致问题?并回答您的第二个问题,doc.qt.digia.com/qt/qmap.html#take
-
QMap::take(..)从地图中删除条目,那么之后将其归零有什么意义呢?它在地图中不存在,并且副本立即超出范围。 -
Blah来自哪里?toDelete = mySomeTypeMap.take(key)从地图中删除索引为key的项目并将其存储在toDelete中。在您调用delete之后,分配给toDelete(局部变量)是没有意义的。问题一定出在其他地方。
标签: c++ qt pointers memory-management qmap