Search code examples
c++pointersnulldestructornullptr

What is a "known bad pointer value"?


In this answer to this question, it was noted that:

If you're going to 'clear' the pointer in the dtor, a different idiom would be better - set the pointer to a known bad pointer value.

and also that the destructor should be:

~Foo()
{
    delete bar;
    if (DEBUG) bar = (bar_type*)(long_ptr)(0xDEADBEEF);
}

I have two question about these parts of the answer.

Firstly, how can you set the pointer to a known bad pointer value? How can you set a pointer to an address which you can assure won't be allocated?

Secondly, what does: if (DEBUG) bar = (bar_type*)(long_ptr)(0xDEADBEEF); even do? What's DEBUG? I couldn't find a macro named so. Also, what's long_ptr? What does it do?


Solution

  • how can you set the pointer to a known bad pointer value? How can you set a pointer to an address which you can assure won't be allocated?

    First, let me be clear that the example code you refer to is a dirty hack and is intended to provide some guidance to assist debugging. It is not intended as a production quality memory management tool; it isn't even intended to be "drop in" code - it's an example of a debugging technique.

    Setting a pointer to a hardcoded value isn't guaranteed to be a "bad pointer" unless you know something about the target environment. 0xDEADBEEF is a value that is likely to be an invalid pointer on many environments just out of luck. The value was chosen in because I had seen it used as a marker for "invalid data" in other code and it is easily spotted when viewing memory dumps. I believe it is (or was, maybe not anymore - that answer was from 14 years ago!) commonly used to indicate memory areas that are invalid/unused. Similar to some of the values Microsoft used in their debug library versions of some memory management routines (see https://stackoverflow.com/a/370362)

    what does: if (DEBUG) bar = (bar_type*)(long_ptr)(0xDEADBEEF); even do? What's DEBUG? I couldn't find a macro named so.

    I might not have said explicitly in the answer you refer to, but the example code might more properly be call a pseudo-code example. if (DEBUG) is used to indicate a bit of code that is conditionally executed "if this is a debug build".

    For example, DEBUG could be a macro (or variable) that is defined as non-zero during a debug build of the problem. Possibly on the compiler's command line (maybe something like -DDEBUG=1). A DEBUG macro is something that I found commonly used for code that is enabled in debug builds only.

    Also, what's long_ptr? What does it do?

    To aid in the transition from 32-bit to 64-bit systems, MS added types that are size of pointers. LONG_PTR is an integer type that has the size of a pointer (32 or 64 bits as appropriate). I probably should have used LONG_PTR instead of long_ptr. I believe the cast is technically unnecessary, but I think it's still useful as a notation that makes clear that an integer is being 'converted' to a pointer - a coding idiom that uses dirty looking casts to call out a dirty hack.