What does Visual Studio do with a deleted pointer and why?

C++PointersVisual Studio-2012Memory ManagementDelete Operator

C++ Problem Overview


A C++ book I have been reading states that when a pointer is deleted using the delete operator the memory at the location it is pointing to is "freed" and it can be overwritten. It also states that the pointer will continue to point to the same location until it is reassigned or set to NULL.

In Visual Studio 2012 however; this doesn't seem to be the case!

Example:

#include <iostream>

using namespace std;

int main()
{
    int* ptr = new int;
    cout << "ptr = " << ptr << endl;
    delete ptr;
    cout << "ptr = " << ptr << endl;

    system("pause");

    return 0;
}

When I compile and run this program I get the following output:

ptr = 0050BC10
ptr = 00008123
Press any key to continue....

Clearly the address that the pointer is pointing to changes when delete is called!

Why is this happening? Does this have something to do with Visual Studio specifically?

And if delete can change the address it is pointing to anyways, why wouldn't delete automatically set the pointer to NULL instead of some random address?

C++ Solutions


Solution 1 - C++

I noticed that the address stored in ptr was always being overwritten with 00008123...

This seemed odd, so I did a little digging and found this Microsoft blog post containing a section discussing "Automated pointer sanitization when deleting C++ objects".

>...checks for NULL are a common code construct meaning that an existing check for NULL combined with using NULL as a sanitization value could fortuitously hide a genuine memory safety issue whose root cause really does needs addressing. > >For this reason we have chosen 0x8123 as a sanitization value – from an operating system perspective this is in the same memory page as the zero address (NULL), but an access violation at 0x8123 will better stand out to the developer as needing more detailed attention.

Not only does it explain what Visual Studio does with the pointer after it is deleted, it also answers why they chose NOT to set it to NULL automatically!


This "feature" is enabled as part of the "SDL checks" setting. To enable/disable it go to: PROJECT -> Properties -> Configuration Properties -> C/C++ -> General -> SDL checks

To confirm this:

Changing this setting and rerunning the same code produces the following output:

ptr = 007CBC10
ptr = 007CBC10

"feature" is in quotes because in a case where you have two pointers to the same location, calling delete will only sanitize ONE of them. The other one will be left pointing to the invalid location...


UPDATE:

After 5 more years of C++ programming experience I realize this entire issue is basically a moot point. If you are a C++ programmer and are still using new and delete to manage raw pointers instead of using smart pointers (which circumvent this entire issue) you may want to consider a change in career path to become a C programmer. ;)

Solution 2 - C++

You see the side-effects of the /sdl compile option. Turned on by default for VS2015 projects, it enables additional security checks beyond those provided by /gs. Use Project > Properties > C/C++ > General > SDL checks setting to alter it.

Quoting from the MSDN article:

> - Performs limited pointer sanitization. In expressions that do not involve dereferences and in types that have no user-defined destructor, pointer references are set to a non-valid address after a call to delete. This helps to prevent the reuse of stale pointer references.

Do keep in mind that setting deleted pointers to NULL is a bad practice when you use MSVC. It defeats the help you get from both the Debug Heap and this /sdl option, you can no longer detect invalid free/delete calls in your program.

Solution 3 - C++

> It also states that the pointer will continue to point to the same location until it is reassigned or set to NULL.

That is definitely misleading information.

>Clearly the address that the pointer is pointing to changes when delete is called! > >Why is this happening? Does this have something to do with Visual Studio specifically?

This is clearly within the language specifications. ptr is not valid after the call to delete. Using ptr after it has been deleted is cause for undefined behavior. Don't do it. The run time environment is free to do whatever it wants to with ptr after the call to delete.

>And if delete can change the address it is pointing to anyways, why wouldn't delete automatically set the pointer to NULL instead of some random address???

Changing the value of the pointer to any old value is within the language specification. As far as changing it to NULL, I would say, that would be bad. The program would behave in a more sane manner if the value of the pointer were set to NULL. However, that will hide the problem. When the program is compiled with different optimization settings or ported to a different environment, the problem will likely show up in the most inopportune moment.

Solution 4 - C++

delete ptr;
cout << "ptr = " << ptr << endl;

In general even reading (like you do above, note: this is different from dereferencing) values of invalid pointers (pointer becomes invalid for example when you delete it) is implementation defined behaviour. This was introduced in CWG #1438. See also here.

Please note that before that reading values of invalid pointers was undefined behaviour, so what you have above would be undefined behaviour, which means anything could happen.

Solution 5 - C++

I believe, you are running some sort of debug mode and VS is attempting to repoint your pointer to some known location, so that further attempt to dereference it could be traced and reported. Try compiling/running the same program in release mode.

Pointers are usually not changed inside delete for the sake of efficiency and to avoid giving a false idea of safety. Setting delete pointer to pre-defined value will do no good in most of complex scenarios, since the pointer being deleted is likely to be only one of several pointing to this location.

As a matter of fact, the more I think about it, the more I find that VS is at fault when doing so, as usual. What if the pointer is const? Is it still gonna change it?

Solution 6 - C++

After deleting the pointer the memory to which it points may still be valid. To manifest this error, the pointer value is set to an obvious value. This really helps the debugging process. If the value were set to NULL, it may never show up as potential bug in the program flow. So it may hide a bug when you test later against NULL.

Another point is, that some run time optimizer may check that value and change its results.

In earlier times MS set the value to 0xcfffffff.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questiontjwrona1992View Question on Stackoverflow
Solution 1 - C++tjwrona1992View Answer on Stackoverflow
Solution 2 - C++Hans PassantView Answer on Stackoverflow
Solution 3 - C++R SahuView Answer on Stackoverflow
Solution 4 - C++Giorgi MoniavaView Answer on Stackoverflow
Solution 5 - C++SergeyAView Answer on Stackoverflow
Solution 6 - C++KarstenView Answer on Stackoverflow