31

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

jww
  • 97,681
  • 90
  • 411
  • 885
Martijn Courteaux
  • 67,591
  • 47
  • 198
  • 287
  • 3
    Out of curiosity, why do you want this? – JSBձոգչ Jul 12 '10 at 16:56
  • Your question is exceedingly implementation specific. For what environment are you asking? – Brian Neal Jul 12 '10 at 16:56
  • 8
    You're forgetting the third possibility: globals and statics. `static int iStatic = 42; int *ptrStatic = &iStatic;` – Mark Ransom Jul 12 '10 at 17:03
  • re your Edit: Neil had it right, and I'd give him a +10, if I could. If you don't know where your pointers are from, you have very serious problems. No amount of hacking will fix it. – sbi Jul 12 '10 at 17:14
  • Well, Martijn, you shouldn't do it that way. Did Neil have it "right?" Maybe if he has psychic powers. Otherwise, he got a lot of votes for jumping on you. – Heath Hunnicutt Jul 12 '10 at 17:18
  • Just because something was allocated with `new` doesn't mean you should call `delete` on it. It may be owned by some other part of the code, which may `delete` it itself, which is bad. It may be used by something else also, and calling `delete` on it will result in something else using deleted memory. It may be a pointer into an allocated block, and not a pointer to the allocated block, in which case `delete` will likely trash your heap and cause a nearly impossible to find problem later. DON'T DO THAT. – David Thornley Jul 12 '10 at 17:27
  • 1
    @Heath: There are questions that naturally come from certain mistaken ways of thinking about things. The reason for asking Martijn's question is usually the one Martijn gave. Moreover, Neil's answer is correct no matter what the reason: there's no way of distinguishing in general (there likely is in many or most implementations), and any design that requires an impossible operation has something wrong with it. – David Thornley Jul 12 '10 at 17:31
  • 1
    @Martijn: I suggest you post your current design as a new question; we'd be happy to help you fix it. – Randolpho Jul 12 '10 at 17:33
  • 4
    @Martijn: You use something called a smart pointer. These objects track the lifetime of what they point to automatically. If you have a class that holds a pointer that is either heap or stack allocated, then that class should not be freeing the memory of that stack/heap. You should do that elsewhere. – Puppy Jul 12 '10 at 18:03

14 Answers14

26

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

  • 23
    -1 for the preachy absolutism. See Carl Norum's answer for how to partially satisfy the OP. – Heath Hunnicutt Jul 12 '10 at 17:01
  • 2
    +1 and Heath, there are good coding practices and bad coding practices. That's why Error'd exists. – mcandre Jul 12 '10 at 17:03
  • 3
    +1 because you are absolutely correct. If you have the problem your design is broken. – Omnifarious Jul 12 '10 at 17:03
  • 17
    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 Jul 12 '10 at 17:05
  • 3
    @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 Jul 12 '10 at 17:07
  • 18
    @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. – GManNickG Jul 12 '10 at 17:08
  • 9
    @Heath If you think my 85K super-powers extend to preventing Martijn from experimenting, you greatly over-estimate them. –  Jul 12 '10 at 17:08
  • 4
    @Neil: Aw, crap. I was hoping when I had 85k I could totally quash all experimentation. Way to shatter my goals, man. – Randolpho Jul 12 '10 at 17:09
  • 1
    @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 Jul 12 '10 at 17:13
  • 1
    @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? – GManNickG Jul 12 '10 at 17:15
  • 1
    @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 Jul 12 '10 at 17:16
  • 1
    @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 Jul 12 '10 at 17:19
  • 3
    @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 Jul 12 '10 at 17:22
  • "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 Jul 12 '10 at 17:25
  • 2
    @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. –  Jul 12 '10 at 17:25
  • 1
    People are confusing "Impossible" with "I don't know how" and "I assume you should not be doing that." – Heath Hunnicutt Jul 12 '10 at 17:28
  • 8
    @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 Jul 12 '10 at 17:30
  • 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 Jul 12 '10 at 17:34
  • 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 Jul 12 '10 at 17:35
  • @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 Jul 12 '10 at 17:46
  • 1
    @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 Jul 12 '10 at 17:49
  • 1
    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 Jul 12 '10 at 18:07
  • 2
    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 Jul 12 '10 at 18:16
  • @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 Jul 12 '10 at 18:21
  • 2
    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 Jul 12 '10 at 18:33
  • 2
    @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 Jul 12 '10 at 19:33
  • 1
    @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 Jul 12 '10 at 20:21
  • 2
    @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. –  Jul 12 '10 at 20:28
  • @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 Jul 12 '10 at 21:00
  • 1
    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 Jul 12 '10 at 22:06
  • 2
    @Rob Then perhaps an answer from you, about using signature-based techniques would be a better bet than these comments? –  Jul 12 '10 at 22:18
  • @anon Well, what about a container Foo that needs to contain at least one valid element from start (likely a vector-like structure). Then I could do new T in the default constructor, but if I now create an array of Foo for later initialization, then you would have an enormous amount of new for nothing. *Note:* I did not say that you need to destinguish this null-element from the others by checking if it belongs to the heap or not. There are better ways (the null-element may also belong to the heap). – user877329 Aug 08 '13 at 18:17
  • Even some small exposition on *why* this isn't a good idea would make this answer much more helpful. I'm sure the book linked to is quite dapper, but comes across as awfully dismissive of the question. – Syndog Jan 17 '14 at 20:09
16

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
  • 219,201
  • 40
  • 422
  • 469
  • 8
    You can't claim that non-stack == heap. – Heath Hunnicutt Jul 12 '10 at 17:00
  • 3
    @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 Jul 12 '10 at 17:05
  • 2
    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 Jul 12 '10 at 17:20
  • 1
    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 Jul 12 '10 at 18:18
12

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.

Evan Teran
  • 87,561
  • 32
  • 179
  • 238
  • You should probably just use a `std::set`, no need to map to anything. Also, should it be removed at delete? – GManNickG Jul 12 '10 at 18:02
  • 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 Jul 12 '10 at 18:03
  • 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. – CB Bailey Jul 13 '10 at 06:27
  • @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 Jul 13 '10 at 11:24
9

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
  • 4,300
  • 18
  • 24
  • 3
    I think the best solution is along those lines, but you have to know the direction of the stack. – Alexandre C. Jul 12 '10 at 17:07
  • 2
    @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 Jul 12 '10 at 17:09
  • 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 Jul 12 '10 at 17:46
  • 1
    @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 Jul 12 '10 at 18:01
  • 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 Jul 13 '10 at 09:18
  • @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 Jul 13 '10 at 12:15
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)

Andrey
  • 59,039
  • 12
  • 119
  • 163
4

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
  • 48,066
  • 12
  • 84
  • 109
  • 4
    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? –  Jul 12 '10 at 17:02
  • 16
    That constant is quite a mouth ffffffffull. – sbi Jul 12 '10 at 17:12
  • 1
    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 Jul 12 '10 at 23:13
  • "In mainstream operating systems..." This has nothing to do with the OS, but depends rather on the hardware architecture: Intel and Sparc grow the stack down, but HP's PA grows it up. – James Kanze Jun 13 '14 at 16:32
  • And of course, even if the stack grows down, there's no guarantee that its start address is at the top of the address space. (It isn't under Windows, for example.) And of course, different threads will have different stacks. – James Kanze Jun 13 '14 at 16:34
3

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
  • 95,107
  • 10
  • 109
  • 188
  • 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 Jul 12 '10 at 17:02
3

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.

2

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
  • 7,631
  • 2
  • 24
  • 30
  • 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)? –  Jul 12 '10 at 19:24
  • 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 Jul 13 '10 at 02:49
  • 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. –  Jul 13 '10 at 18:21
2

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 its lifetime.

Adrian McCarthy
  • 45,555
  • 16
  • 123
  • 175
Jay
  • 13,803
  • 4
  • 42
  • 69
1

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
  • 59,039
  • 12
  • 119
  • 163
0

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
  • 54,333
  • 19
  • 131
  • 194
0

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
  • 39,638
  • 28
  • 112
  • 212
0

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
  • 507
  • 4
  • 3