问题
I'm having what seems to be a weird issue, but it could be a quirk of how QMap's work and I just don't understand it. It's tough to summarize the problem, but I'll do my best.
I have a class A
, with a QMap<QString, someType*> mySomeTypeMap;
. When I load a new file in my program, I want to delete all the contents of this QMap
so I can repopulate it with new data. I do that by doing the following:
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;
}
The qDebug()
statement prints out the correct address of the value I want to delete, and when I look at toDelete
in the debugger after it gets set to NULL
, it says 0x0, which is what I want.
Then later, in a different class B
, I have the following code...
void B::setSomeType(someType* blah)
{
if (Blah != NULL)
{
//Calls a bunch of disconnect()'s
disconnectAllSignals();
Blah = blah;
//Calls a bunch of connect()'s
connectAllSignals();
}
}
Now, what's really confusing is my program crashes when it gets to the disconnectAllSignals();
line. The reason being it's trying to call disconnect()
on Blah
which was deleted and should have been set to 0x0 when I set it to NULL
. However, if it was actually set to NULL
it never would have entered that if-block to begin with. In a debugger, I see that the address of Blah
is exactly the same as what I get when I print out qDebug() << "toDelete: " << toDelete;
right before setting toDelete = NULL;
.
TLDR; I don't know how my program is getting the orignal address of a pointer back after I delete the pointer and set the same pointer to NULL
. Since the pointer isn't set to NULL
later in the execution it leads to a crash.
回答1:
Values in the map are stored by value even if in these case it means that the pointer (address which it points) is stored by value. For example:
someType* toDelete1 = mySomeTypeMap.take(key);
someType* toDelete2 = mySomeTypeMap.take(key);
someType* toDelete3 = toDelete1;
toDelete1 = NULL;
toDelete2 & toDelete3 will still point to the original object
Instead of making the pointer null after delete you should either remove it from the map or set the value for that key to NULL.
回答2:
someType* toDelete = mySomeTypeMap.take(key);
This is a pointer variable created on stack and its value is set to the value that you keep in map. You dont need to set it to NULL, because it goes out of scope right away.
take
function is removing pointer from the map, if you use it again with the same key it will return default-constructed value. Just after delete
try to
mySomeTypeMap.insert(key, 0);
来源:https://stackoverflow.com/questions/14340672/invalidate-pointer-values-inside-a-qmap