views:

812

answers:

14

The title says it all.

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

And I have an excuse for why I though to do it that way:
I'm a beginner :-)

+26  A: 

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++.

anon
+1. Precisely what I was thinking.
Fred Larson
-1 for the preachy absolutism. See Carl Norum's answer for how to partially satisfy the OP.
Heath Hunnicutt
+1 and Heath, there are good coding practices and bad coding practices. That's why Error'd exists.
mcandre
+1 because you are absolutely correct. If you have the problem your design is broken.
Omnifarious
StackOverflow has come to telling questioners they are "doing it wrong" for 85.5k of rep. Sweeeeet. I'm curious why Martijn thinks he wants to do this, too, but why tell him off? Let him experiment.
Heath Hunnicutt
@Heath: that's outright unfair. Neil is absolutely correct; if you need to know whether or not a pointer is on the stack, you've got to go back to the drawing board.
Randolpho
@Heath: There's nothing to experiment about. It's not possible. That's like having OP say "I want to draw a square with no edges." and we say "You can't." and you feel we should let him experiment. (Which he still can, by the way.) What exactly is he to do, and what kind of answer would you prefer? This is a great answer in it even points to other resources to find out why he can't, from leading C++ programmers no less.
GMan
@Heath If you think my 85K super-powers extend to preventing Martijn from experimenting, you greatly over-estimate them.
anon
@Neil: Aw, crap. I was hoping when I had 85k I could totally quash all experimentation. Way to shatter my goals, man.
Randolpho
@GMan: It's easy to determine if an address is from the stack, on most any environment or OS. See Norum's answer. So, the OP can be at least half-answered in an honest way. Determining is an address "of the heap" is an exercise in wrongness, I agree. But a person could explain why. And most importantly DISTINGUISH between what is truly (honestly, not lying or disingenuously...) "impossible" vs. "unfashionable."
Heath Hunnicutt
@Heath: Which OS is C++ tied to? Which OS is OP using? There's no way to do it in C++. It's impossible; any attempts will lead to undefined behavior. Do you skip the part where Norum's answer is completely OS dependent?
GMan
@Heath: Just look at Martijn's edit, where he writes why he needs that. Neil hit the nail right on the head (and so did GMan, FTM). __You should not need that!__ is the best answer to such questions, because for the few cases where you really need that, you're supposed to be at a level where you don't need to ask such questions.
sbi
@sbi: That is valid. Unfortunately, the information wasn't available when Neil and others decided the best thing to do was jump snarky on the OP. Turning out to be "justified" in the end doesn't actually justify, anyway.
Heath Hunnicutt
@Heath: You thought this answer was snarky?
GMan
@Heath: No, you're wrong. If someone really needs this, they ought to know what they are doing (and if they were asking, they'd explain why they do that). For everyone else, Neil simply spoke the truth. Now be a good citizen and remove your down-vote. (Not that those -2 would hurt Neil.)
sbi
"I want to draw a square with no edges." That's easy, you just disable the stroke for your current style. Of course, this depends on your definition of "edge". Also what you're actually drawing with.
JAB
@Heath If you think this answer is "snarky" (a word I've never quite understood, but I assume to be kewl-speak for "sarcastic") you obviously are not a follower of my posts here.
anon
+1 for correctly using absolutism.
Amardeep
People are confusing "Impossible" with "I don't know how" and "I assume you should not be doing that."
Heath Hunnicutt
@Heath: but he was absolutely correct in his first phrase: "there is no way of doing this". There absolutely is no way to do what the OP asked, period, end of story. It's entirely system dependent. Not just OS dependent, but *system* dependent; different CPU architectures running the same OS will still have different needs in order to track down the information. The sheer number of combinations makes such a function nearly impossible to build -- it might not even be possible to gather the necessary information at runtime. The *correct* answer is to go back to the drawing board.
Randolpho
@JAB: A square with no edges is a common example of an impossible object. A square has four edges, by definition, so it cannot be drawn without edges. If you do, you haven't drawn a square since it doesn't have four edges. @Heath: I'm not confusing anything. There's no way to do it in C++. If the OP would like to give his specific platform (everything about it) and compiler (everything about it), we might have a chance at (wasting time and) finding a solution (which would be 100% non-standard C++). Better is to take the gun away from the child though, instead of try to teach him how to use it.
GMan
I don't get why people are complaining about this answer. It's a fact that if you have control over the design, you can just choose whether you want to stack-, heap-, or static-allocate your pointers. Just pick one and stick with it! In C++, assuming you're using a class, just make sure your constructor and destructor use consistent methods. If it's stack-allocated you can assign the address-of if needed in the constructor and do nothing in the destructor; if heap-allocated, use new/delete (or malloc/free if you're masochistic); if static-allocated, all that code is outside functions anyway.
Platinum Azure
And if you're NOT in a class, fine, just pick a method and stick with it. You really shouldn't have a need for a pointer to either stack or heap space.
Platinum Azure
@Platiunum, imagine, hypothetically, that Martijn had been told to unit test a library which must return a pointer allocated with malloc(). How could he verify that requirement? You can't simply call free(), because it might coincidentally fail silently, appearing as if nothing were wrong with freeing that pointer.
Heath Hunnicutt
@Heath: No, people are not confusing "impossible" with anything but "impossible". A programming language specification is a mathematical construct, and so it is possible to say that something can or cannot be done in standard C++. By knowing several different implementations, it's possible to know if something can or cannot be done using common extensions. You'll notice that Carl Norum's answer is for a specific implementation, and differs from other such answers, which are also for specific implementations.
David Thornley
But @David, the C++ standard is not a *complete* mathematical construct. There are many holes in it, labeled as "undefined" and "unspecified." Implementations are free to fill those holes as long as they don't violate what's already in the standard. A program that uses such constructs is still a conforming C++ program. If a certain implementation and environment make it possible to distinguish stack and heap addresses without violating the standard, then it's incorrect so say that the distinction is absolutely impossible.
Rob Kennedy
As a side note, determining whether something is "on the stack" or "on the heap" is pointless with respect to determining the validity of `delete`, if only because there's absolutely no guarantee that automatic storage duration in a particular C++ implementation corresponds to the OS stack. A conformant compiler is free to stuff locals onto the OS heap, and clean it up on return.
Pavel Minaev
@Rob: Of course - but if you're using something in the holes you're no longer using standard C++. Similarly, I know of various extensions in some compilers, but they don't support telling what memory area a pointer is pointing to. The OP mentioned neither an OS nor an implementation, so it's reasonable to assume OP was asking for a halfway general solution, which does not exist. Similarly, the fact that I can write specific programs that will definitely terminate, and some that don't, doesn't mean the Halting Problem is solvable.
David Thornley
It's not automatically a violation of the standard to invoke undefined behavior, @David. It's still standard C++. The standard merely doesn't say what should happen. A *general* solution doesn't exist, but that doesn't mean that *no* solution exists at all. Neil's answer makes no such distinction, but I think it should.
Rob Kennedy
@Rob: I fail to understand why any definition of "standard C++" that includes nonconforming programs is useful. Nor do I see why the probable existence of some highly implementation-specific solutions means that a solution is generally possible, especially since the OP did not mention implementation details. I really don't see the value in Neil saying that it might be possible to get a mostly-correct solution in a very system-dependent way if we knew the exact implementation details. There may be systems that guarantee how `i++ + i++` is evaluated; shall we mention that?
David Thornley
@David, we're not talking about nonconforming programs. And no one ever said that a general solution is possible. When implementation details are absent from a question, a good response is to say that it depends on implementation details, and perhaps listing answers some some of the more common implementations, not to say that it's flat-out impossible (which, in light of some other answers here, is misleading, if not plain wrong). [And here are two answers discussing an expression similar to `i++ + i++`](http://stackoverflow.com/questions/1860461/) that don't just say "you can't do that."
Rob Kennedy
@Rob I don't really see what you are getting excited about - if you don't think my answer is correct, downvote it. And please, if you haven't already done so, read the bit in More Effective C++ I mentioned.
anon
@Rob: However, any attempt to check where a pointer came from is going to involve undefined behavior, and hence nonconforming programs. Nor are any of the answers I read here necessarily accurate, since they usually check whether the pointer is in one certain stack space or mark the pointer specially, while the OP wanted one that would work for pointers returned from functions. In other words, it's impossible without dubious system-dependent hacks; is that worth specifying for every answer, given the number of things that can probably be done with dubious system-dependent hacks?
David Thornley
My issue is that @Randolpho et al have gotten on the bandwagon saying that it's absolutely impossible to distinguish between heap and stack addresses when there are counterexamples in other answers. Especially David, who, in his comment to the question, contradicts that absolute statement by saying "there likely is [a way of distinguishing] in many or most implementations." I completely agree that the *need* to distinguish between them indicates a bad design and should be avoided. Also, Meyers writes, "I have since become convinced that signature-based techniques are all but foolproof."
Rob Kennedy
@Rob Then perhaps an answer from you, about using signature-based techniques would be a better bet than these comments?
anon
+8  A: 

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;
Carl Norum
You can't claim that non-stack == heap.
Heath Hunnicutt
@Heath, absolutely true. But given the appropriate access to OS structures or linker-defined variables, you can eliminate the other non-heap regions. That's why I said "something like". The `isHeapPointer` is just because of the OP's nomenclature. Editing now.
Carl Norum
@Carl, like the edit. One can surely determine whether an address is from "the stack" or "a stack." A process should check each thread's stack, if there are more than one threads per process.
Heath Hunnicutt
In modern operating system likes the "stack" may not necessarily be implemented as a "stack data structure". I remember reading an article where they were trying to prevent stack overrun exploits by putting stack segments randomly through memory (ie as part of the heap). If your OS uses this technique then you are out of luck.
Martin York
+2  A: 

In mainstream operating systems, the stack grows from the top while the heap grows from the bottom. So you might heuristically check whether the address is beyond a large value, for some definition of "large." For example, the following works on my 64-bit Linux system:

#include <iostream>

bool isHeapPtr(const void* ptr) {
  return reinterpret_cast<unsigned long long int>(ptr) < 0xffffffffull;
}

int main() {
  int iStack = 35;
  int *ptrStack = &iStack;
  std::cout << isHeapPtr(ptrStack) << std::endl;
  std::cout << isHeapPtr(new int(5)) << std::endl;
}

Note that is a crude heuristic that might be interesting to play with, but is not appropriate for production code.

Philipp
Well, your statements about the stack and heap might be true, except that there can be multiple heaps, multiple stacks, and what about static variables?
anon
That constant is quite a mouth ffffffffull.
sbi
Please change your answer from "modern operating sytems" to "mainstream operating sytems". I work on several modern operating systems where you answer will not apply.
Brian Neal
@Brian Neal: Thanks, done.
Philipp
+3  A: 

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.

Gianni
I think the best solution is along those lines, but you have to know the direction of the stack.
Alexandre C.
@Alexandre Yes, it is a trial-and-error thing really. It will never give you a satisfying answer, but will quench your curiosity and teach you something about memory layout.
Gianni
no, this will not work. stack grows towards smaller addresses, so for any local var address will be greater than ESP. But for all head addresses this statement also will be true
Andrey
@Andrey Like I said in the comment above, it won't work in many cases, but then again, I don't think anything will; except a full blown comparison of all stack pointers and stack bases and having intimate knowledge of your program's layout in RAM.
Gianni
no, there is a way to find top and bottom of the stack, i googled a bit and found it: http://stackoverflow.com/questions/3230420/c-how-to-know-if-a-pointer-points-to-the-heap-or-the-stack/3230873#3230873
Andrey
@Andrey The code I pasted above is from a test case I made once, and it worked fine! It was able to detect with 100% accuracy my simples cases. Once again, I *know* it will never work 100% of the time, but still, it is interesting to try and find out *why8 it doesn't work.
Gianni
+2  A: 

First, why do you need to know this? What real problem are you trying to solve?

The only way I'm aware of to make this sort of determination would be to overload global operator new and operator delete. Then you can ask your memory manager if a pointer belongs to it (the heap) or not (stack or global data).

Mark B
This is an OK way to determine what came from the heap if it was allocated in your own source code. But it doesn't help you with pointers from some other API.
Heath Hunnicutt
A: 

The only way I know of doing this semi-reliably is if you can overload operator new for the type for which you need to do this. Unfortunately there are some major pitfalls there and I can't remember what they are.

I do know that one pitfall is that something can be on the heap without having been allocated directly. For example:

class A {
   int data;
};

class B {
 public:
   A *giveMeAnA() { return &anA; }
   int data;
   A anA;
};

void foo()
{
   B *b = new B;
   A *a = b->giveMeAnA();
}

In the above code a in foo ends up with a pointer to an object on the heap that was not allocated with new. If your question is really "How do I know if I can call delete on this pointer." overloading operator new to do something tricky might help you answer that question. I still think that if you have to ask that question you've done something very wrong.

Omnifarious
+4  A: 

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)

Andrey
A: 

How could you not know if something is heap-allocated or not? You should design the software to have a single point of allocation.

Unless you're doing some truly exotic stuff in an embedded device or working deep in a custom kernel, I just don't see the need for it.

Look at this code (no error checking, for the sake of example):

class A
{
int *mysweetptr;

A()
{
   mysweetptr = 0; //always 0 when unalloc'd
}

void doit()
{
   if( ! mysweetptr)
   {
       mysweetptr = new int; //now has non-null value
   }
}

void undoit()
{
   if(mysweetptr)
   {
      delete mysweetptr;
      mysweetptr = 0;  //notice that we reset it to 0.
   }
}

bool doihaveit()
{
   if(mysweetptr)
     return true;
   else 
     return false; 
}
~A()
{
   undoit();
}
};

In particular, notice that I am using the null value to determine whether the pointer has been allocated or not, or if I need to delete it or not.

Paul Nathan
A: 

here is universal way to do it in windows using TIP:

bool isStack(void* x)
{
    void* btn, *top;
    _asm {
        mov eax, FS:[0x08] 
        mov btn, eax
        mov eax, FS:[0x04] 
        mov top, eax
    }
    return x < top && x > btn;
}

void func()
{

    int i;

    bool b1;
    bool b2;

    b1 = isStack(&i);
    b2 = isStack(&si);

    return;
}
Andrey
+6  A: 

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*> map_;
        return map_;
    }

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.

Evan Teran
You should probably just use a `std::set`, no need to map to anything. Also, should it be removed at delete?
GMan
good calls, updated :-). Yea I think it should be removed at delete because the address could hypothetically be reused by just about any other type of object. I don't think it makes it less functional.
Evan Teran
Although this answers the question "can I delete this pointer", rather that the less useful "does this point to the heap" there are still potential issues with the approach. In general if you do (e.g.) `new T[4]` followed by `new X` the legitimate (if not dereferencable) pointer to one past the end of the `T` array might have the same numeric value as the pointer to the dynamically allocated X even though they are of different types.
Charles Bailey
@Charles Bailey: Sure, I suppose that `is_heap` could take a `T*` to slightly increase safety, but to be honest, I think we all agree that the OP was asking to do something that we all know is not a good idea. Surely any and all solutions will have some flaws.
Evan Teran
+2  A: 

Despite loud claims to the contrary, it is clearly possible to do what you want, in a platform-dependent way. However just because something is possible, that does not automatically make it a good idea. A simple rule of stack==no delete, otherwise==delete is unlikely to work well.

A more common way is to say that if I allocated a buffer, then I have to delete it, If the program passes me a buffer, it is not my responsibility to delete it.

e.g.

class CSomething
{
public:
    CSomething()
    : m_pBuffer(new char[128])
    , m_bDeleteBuffer(true)
    {
    }

    CSomething(const char *pBuffer)
    : m_pBuffer(pBuffer)
    , m_bDeleteBuffer(false)
    {
    }

    ~CSomething()
    {
        if (m_bDeleteBuffer)
            delete [] m_pBuffer;
    }

private:
    const char *m_pBuffer;
    bool        m_bDeleteBuffer;
};
Michael J
Possible? Really? Your library can know, before it is compiled and linked, whether the applications it will be linked to are multithreaded (multiple stacks) or use DLLs (multiple heaps)?
Steve314
You seem to have missed my point. Yes, I do believe it is possible, but that is a moot point. My main point is "don't do it".
Michael J
I get and agree with your main point, but that doesn't mean I'm not allowed to disagree with some minor point you made along the way. You did say "platform-dependent", so bonus points for that, but even then... for example, the heap is just a data structure - it's a mistake to assume it must be implemented by "the platform". Even ignoring the problems of custom allocators, there's also the problem of multiple compilers for multiple DLLs - each with its own runtime and therefore it's own heap implementation.
Steve314
+1  A: 

You're trying to do it the hard way. Clarify your design so it's clear who "owns" data and let that code deal with it's lifetime.

Jay
A: 

Your design should not rely on determining this information (as others have pointed out, it's not really possible). Instead, your class should explicitly define the ownership of pointers that it takes in its constructor or methods. If your class takes ownership of those pointers, then it is incorrect behavior to pass in a pointer to the stack or global, and you should delete it with the knowledge that incorrect client code may crash. If your class does not take ownership, it should not be deleting the pointer.

Mike McNertney
+1  A: 

Even if you could determine whether a pointer was on one particular heap, or one particular stack, there can be multiple heaps and multiple stacks for one application.

Based on the reason for asking, it is extremely important for each container to have a strict policy on whether it "owns" pointers that it holds or not. After all, even if those pointers point to heap-allocated memory, some other piece of code might also have a copy of the same pointer. Each pointer should have one "owner" at a time, though ownership can be transferred. The owner is responsible for destructing.

On rare occasions, it is useful for a container to keep track of both owned and non-owned pointers - either using flags, or by storing them separately. Most of the time, though, it's simpler just to set a clear policy for any object that can hold pointers. For example, most smart pointers always own their container real pointers.

Of course smart pointers are significant here - if you want an ownership-tracking pointer, I'm sure you can find or write a smart pointer type to abstract that hassle away.

Steve314