In this paragraph of C++ FAQ usage of delete this
construct is discussed. 4 restrictions are listed.
Restrictions 1 to 3 look quite reasonable. But why is restriction 4 there that I "must not examine it, compare it with another pointer, compare it with NULL, print it, cast it, do anything with it"?
I mean this
is yet another pointer. Why can't I reinterpret_cast
it to an int
or call printf()
to output its value?
because any action you can take with that pointer could trigger logic which is interpreted on the class methods of that object, which could lead to a crash.
Now, some of the actions you point at could be apparently "safe", but it's difficult to say what happens within any method you can call.
From the post: "must not examine it, compare it with another pointer, compare it with NULL, print it, cast it, do anything with it"?
All these actions can trigger operator related functions, which are evaluated with an undefined pointer. Idem for casting.
Now if you perform a reintepret_cast, that's probably a different story, and you could probably get along with it, as reinterpret is just a bit by bit reinterpretation, without involving (as far as I know) any method call.
b/c the address that this refers to now, it undefined, and you don't know what might be there...
In a multi-threaded program, the moment you
delete
a pointer, the free space can be allocated by another thread, overwriting the space used bythis
. Even in a single-thread program, unless you're very careful about what you call beforereturn
ing, anything you do afterdelete this
could allocate memory and overwrite what used to be pointed to bythis
.In a Microsoft Visual C++ executable compiled in Debug mode,
delete
ing a pointer causes its memory to be immediately overwritten with a 0xCC test pattern (uninitialized variables are also initialized with this pattern), to help in identifying dangling pointer bugs such as this one.This reminds me of when I fixed a bug in a online-playable game in which a Fire object's constructor deleted the oldest Fire if the total number of Fires had reached a certain number. The deleted Fire was sometimes the parent Fire creating a new Fire — bam, dangling pointer bug! It was only due to luck that this bug interacted with the memory allocation algorithm in a completely predictable way (the deleted Fire was always overwritten with a new Fire in the same way) — otherwise it would have caused a desynchronization between online players. I found this bug when rewriting the way the game did memory allocation. Due to its predictability, when I fixed it, I was also able to implement emulation of its behavior for compatibility with older game clients.
Aha!
3.7.3.2/4: "... the deallocation function shall deallocate the storage referenced by the pointer, rendering invalid all pointers referring to any part of the deallocated storage. The effect of using an invalid pointer value (including passing it to a deallocation function) is undefined".
Note that this says "using the value", not "dereferencing the pointer".
That paragraph is not specific to
this
, it applies to anything that has been deleted.For the same reason you would not delete any other pointer and then try and perform any operations on it.
The reason that you cannot do anything with a pointer after you delete it (this, or any other pointer), is that the hardware could (and some older machines did) trap trying to load an invalid memory address into a register. Even though it may be fine on all modern hardware, the standard says that the only thing that you can do to a invalid pointer (uninitialized or deleted), is to assign to it (either NULL, or from another valid pointer).