How to know if a pointer points to the heap or the stack?

Example:

bool isHeapPtr(void* ptr)
{
     //...
}

int iStack = 35;
int *ptrStack = &iStack;
bool isHeapPointer1 = isHeapPtr(ptrStack); // Should be false
bool isHeapPointer2 = isHeapPtr(new int(5)); // Should be true
/* I know... it is a memory leak */

Why, I want to know this:

If I have in a class a member-pointer and I don't know if the pointing object is new-allocated. Then I should use such a utility to know if I have to delete the pointer.

But:
My design isn't made yet. So, I will program it that way I always have to delete it. I'm going to avoid rubbish programming


Solution 1:

There is no way of doing this - and if you need to do it, there is something wrong with your design. There is a discussion of why you can't do this in More Effective C++.

Solution 2:

In the general case, you're out of luck, I'm afraid - since pointers can have any value, there's no way to tell them apart. If you had knowledge of your stack start address and size (from your TCB in an embedded operating system, for example), you might be able to do it. Something like:

stackBase = myTCB->stackBase;
stackSize = myTCB->stackSize;

if ((ptrStack < stackBase) && (ptrStack > (stackBase - stackSize)))
    isStackPointer1 = TRUE;

Solution 3:

The only "good" solution I can think of is to overload operator new for that class and track it. Something like this (brain compiled code):

class T {
public:    
    void *operator new(size_t n) {
        void *p = ::operator new(n);
        heap_track().insert(p);
        return p;
    }

    void operator delete(void* p) {
        heap_track().erase(p);
        ::operator delete(p);
    }

private:

    // a function to avoid static initialization order fiasco
    static std::set<void*>& heap_track() {
        static std::set<void*> s_;
        return s_;
    }

public:
    static bool is_heap(void *p) {
        return heap_track().find(p) != heap_track().end();
    }
};

Then you can do stuff like this:

T *x = new X;
if(T::is_heap(x)) {
    delete x;
}

However, I would advise against a design which requires you to be able to ask if something was allocated on the heap.

Solution 4:

Well, get out your assembler book, and compare your pointer's address to the stack-pointer:

int64_t x = 0;
asm("movq %%rsp, %0;" : "=r" (x) );
if ( myPtr < x ) {
   ...in heap...
}

Now x would contain the address to which you'll have to compare your pointer to. Note that it will not work for memory allocated in another thread, since it will have its own stack.

Solution 5:

here it is, works for MSVC:

#define isheap(x, res) {   \
void* vesp, *vebp;     \
_asm {mov vesp, esp};   \
_asm {mov vebp, ebp};    \
res = !(x < vebp && x >= vesp); }

int si;

void func()
{
    int i;
    bool b1;
    bool b2;
    isheap(&i, b1); 
    isheap(&si, b2);
    return;
}

it is a bit ugly, but works. Works only for local variables. If you pass stack pointer from calling function this macro will return true (means it is heap)