tags:

views:

94

answers:

3

I'm wondering if it's possible to determine if a given address is on the stack or in the heap. I'd like this because a reference counting system we use has a flaw that if a smart pointer is somehow pointed at an object on the stack, bad things can happen. If I had this functionality, I could use it to detect this error condition early and throw so that the developer doing this would be forced to deal with this immediately.

+1  A: 

No, this is not possible or supported. (Well, it may be possible if you want to rely on undefined or implementation defined behavior... I strongly advise you to not do that.) The typical explanation of stack and heap taught in Computer Science courses has very little in common with how real systems (which use Virtual Memory) operate.

Generally speaking it is not worth it. (If it was, std::auto_ptr, std::unique_ptr, or boost::shared_ptr, or boost::scoped_ptr would do it) C and C++ users are generally used to working with APIs which allow undefined behavior if the user does something stupid. Particularly when storage locations (stack versus free store) are concerned.

Billy ONeal
What if it was a debug build only feature (I.E. it got compiled out)... Im not arguing for this as a feature, just as a safety mechanism while developing software... Yes C/C++ programmers are used to unsafe environments, but that doesn't mean we shouldn't try to help them!
dicroce
@dicroce: That would not make any sense. When you tried to `delete` the pointer to the stack allocated object, you're going to crash. That will flag the problem just as simply. The only reason you'd ever want to do this would be for runtime crash protection.
Billy ONeal
yes. I'm trying to detect that before... If the reference is squirreled away, that might be MUCH later in the program... and that would make tracking it down MUCH harder... A debug build only check at assignment to the ref time would cause the error to be found much sooner.
dicroce
@dicroce: In a debug build, when the application crashes as a result of trying to delete [or free, since you haven't been particularly clear on what language you're using] a stack pointer, you should have more than enough information available to identify the problem anyhow. Like Billy said; if this were reliably possible, debug builds of existing smart pointers would probably already employ it.
Dennis Zickefoose
If I declare an object on the stack, then in the same function pass a reference to it to another function which copies that reference into a member variable of a long lived object it may not crash until that object goes away, which could be an indeterminate amount of time later. If however, there was a way to detect at assignment that this address was on the stack, I could throw immediately in the function that caused the problem. Which is way easier to track down.
dicroce
@dicroce: No; because when the object is deleted, a debugger knows exactly on the stack where that item came from, and can therefore peg exactly where that variable came from. You should be able to follow how it got into the reference counted object from there.
Billy ONeal
I take back what I just said. The crash is likely to happen well before calling delete/free, since the variable will have probably fallen out of scope at some point.
Dennis Zickefoose
@Billy ONeal: But that stack address could have been used by every function in the program if it was low enough. It's a stack, it grows and shrinks and grows again using the same bits. The address on the stack later, means NOTHING...
dicroce
@dicroce: Okay, but if you've gotten to the point where the address on the stack no longer points to a valid location, you're going to crash as soon as somebody tries to dereference the pointer. It's just not worth it to attempt to catch this kind of problem.
Billy ONeal
Im not trying to catch it. I WANT to throw, but I want to do it when the reference is assigned, not crash hours later.
dicroce
@dicroce: I don't mean catch with respect to exception handling, I mean catch as a synonym of detect. ;)
Billy ONeal
@Billy ONeal: Both options "detect" the problem. One, immediately, in the function that it occured... and the other potentially hours later when the stashed reference is used (yes, it will probably immediately use it, and in those cases, finding this would be easy, but in the case it just copies the ref away, this problem would be nasty to find).
dicroce
@dicroce: Yes, but the one immediately relies on unspecified behavior, complicates the program, results in additional code you have to maintain, and incurs runtime cost. These things don't come for free.
Billy ONeal
@Billy ONeal: The title of the question specifically mentions I am looking for a GCC solution! Not an Ansi-C/C++ standard solution... An "implementation defined" solution is fine in this case...
dicroce
+2  A: 

Any solution would have to be platform specific. In Windows, you can use HeapWalk to enumerate all chunks of memory in the heap. In Unix, you can try to use pthread_attr_getstack().

Not entirely correct on Windows -- HeapWalk can walk the blocks for *a* heap. But on Windows, there is typically more than one heap.
Billy ONeal
and you can enumerate heaps with GetProcessHeaps().
Thank you! It looks like pthread_attr_getstack() is exactly what I was looking for.
dicroce
+2  A: 

The direct answer to your question is that GCC supports inline assembly language, which will let you compare pointers to the stack pointer.

But you might prefer forcing your objects to be heap-allocated so you won't have this problem in the first place.

dan04
Knowing the location of the pointer wrt the stack pointer is not enough to get reliable answers to the question. You need to know the size and the base of the stack.
+1 for suggesting the only reasonable answer to this program that doesn't rely on undefined or implementation defined behavior.
Billy ONeal
pthread_attr_getstack() looks pretty well defined to me.
dicroce
@dicroce: Did you see the second part of that sentence: "implementation defined"? Because pthread_attr_getstack() is not a standard C or C++ function. Using it locks you to a particular implementation (namely, POSIX).
Billy ONeal
The title of the question specifically mentions GCC! NOT Ansi-C...
dicroce
@dicroce: Yes, I can see that. But 1. POSIX != GCC; MinGW will fail to compile the code built with that function call. And 2. just because you *can* use a platform specific extension does not mean that it is a good idea.
Billy ONeal
@Billy ONeal: 1) Look, I thought specifying that I'm ok with a GCC specific solution would imply that I am ok with non ansi standard solution. 2) Can you honestly say that you've built non trivial applications without any platform specific code? Seriously? So I guess you don't use threads in your code? How is pthread_create() (or even Win32's CreateThread()) ok for use but pthread_attr_getstack() not? It's seems far more likely to me that you're just being stubborn.
dicroce
@dicroce: I'm not saying there's no need for platform specific code. I'm saying that falling on platform specific to enforce something like this doesn't make any sense.
Billy ONeal
But it's just an extra safety check! Oh, I give up...
dicroce