Determine if c++ Object are on stack or on heap ...

Started by
17 comments, last by jpetrie 16 years, 10 months ago
Hello. I have a problem with my smart pointer system: Suppose i create an object on the stack, and then, i reference this object using a smart pointer. When the object get out of scope it is automaticaly destroyed ( because it's on the stack ), but, my smart pointer is still pointing to it, and when the smart pointer get destroyed, it try do delete an object that do not exist anymore .... :( Since a few hours, i'm looking over the web, to find a way to determine if an object is on the stack or on the heap, but i didn't find any solution to this problem .... Do you ever encounter this problem??? Can you give me some clues on how to solve this problem ??? Thanks a lot !! Clement
Advertisement
Well, it's probably possible to get the address of the bottom and top of the stack and check if the pointer is in this range. However, this is not the answer. The answer is that you should NEVER be pointing to a stack-allocated object using a smart pointer.

If you have a section of code that you know isn't going to be deleting an object, then there's no reason to reference the object via a smart pointer there - just use a normal pointer or a reference.
You really, really don't want to do this, what would be the point? The solution is not to use smart pointers - its not what they were designed for. If you have to pass in a smart pointer, you need to allocate the object on the heap.

It sounds like you are trying to work around a design problem elsewhere in your system.
The main problem is that you use a smart pointer (or any pointer for that matter) to reference an object that is on the stack. I would definitely recommend against this.

First of all, try to solve the problem without referencing a stack object with a pointer.

Next - if you insist on doing this, there are many (very ugly) things you can do. For example, you can have a flag in your smart pointer class, and you can set the object to be dynamic/static, therefore causing the smart ptr to release it (or not). This is just one possible course of action. There are many more ideas that can help you - but if you'll look into the design you'll find that the main problem is referencing a stack object with a smart pointer. If you want, you can tell us why do you need to do such a thing - and maybe someone will have a better idea for you.
Dubito, Cogito ergo sum.
If your smart pointer implements the semantics of a weak pointer (become a null pointer when the referenced object is deleted to prevent a dangling pointer) then you are fine.

To distinguish between an object being on the stack vs. being on the heap you have two options:
1) Implement your own heap manager to know the address ranges of objects that were allocated on the heap. Your smart pointer can then check if the address its pointing to is within one of those ranges. (Note that you can delegate the actual work of memory management to new/delete.)
2) For every thread (each has its own stack) take the address when the thread is started. When your smart pointer needs to determine if the address its pointing to refers to the stack, it has to check if that address falls into the range between the marker and the current stack pointer for each thread.

Unless your smart pointer class is utterly brain-dead, pointing to a stack object should not pose an problem implementation problem. Well-designed smart pointer classes such as boost::shared_ptr allow you to provide the destruction function (because you'd need it to differentiate new and malloc anyway).

The main problem here is a semantic one: the intended use of a (non-weak) smart pointer is to share ownership of the variable. However, a stack variable is owned by the scope it lives in, and that ownership cannot be shared. You can still make the assumption that the variable will not go out of scope while still in use:

T t;{  boost::shared_ptr<T> p( &t, NOP() );  // ... use the smart pointer ...  assert (p.unique());}


However, this is brittle and prone to errors even if tested thoroughly. It is best to simply allocate the object on the heap and delegate ownership to the smart pointer.
I somehow miss the point of this.

How can you run into such situation in the first place?

Objects "allocated" on stack are completely different. While its constructor and destructor are called, the memory allocation is implied by the compiler.

Heap allocated objects are explicitly allocated by the user, and need to be de-allocated explicitly. So if you run into a situation like this it's likely a design issue.

I use stack allocated memory in network and messaging code. The dependant code gets these variables by const reference. This way, if the data needs to be modified it's necessary to copy it in the first place, and storing references is a tricky and unadvisable in the first place.

I'd strongly advise you to rethink your design if you run into such situation. I'd suggest passing objects by reference in the first place, and only use smart pointers for dynamically allocated objects.

The other is obviously to pass a flag to smart pointer to indicate whether it owns data or not. If not, the destructor will not attempt to de-allocate the data smart pointer points to.

I used the later technique in memory buffer design, but I ensure the data gets properly allocated/de-allocated with use of class design, where buffers can only be obtained in such a way that memory ownership issues don't arrise - these buffers deal with exactly such a problem. When serializing data, they use stack allocated buffer. If this buffer gets too small, bigger one is allocated on the heap. Buffers get passed around by const reference as well.

Disregarding all the reasons why you shouldn't do this (Don't do this) there are platform specific ways to do this (Don't do this). In MSVC, _CrtIsValidHeapPointer will tell you if a pointer is into the heap or not (Don't do this) but it only works in debug.
I understand, that it's not the purpose of smart pointer to point to stack allocated object.

But the thing is that now, i must create all "smart pointed" object on the heap, which is not relly a problem on it's own...
It's just that sometime it's more "simple" to let the stack system create and destroy the object...

Fo exemple, if i need to create a file object ( which is referenceable in my system ), in order to use it in a simple loading function, actually i must allocate it on the heap....

But it would be more convenient to be able to also use it as a stack allocated object ....

Anyway ...

I think i'm gonna use the _CrtIsValidHeapPointer in order to detect when a smart pointer try to point to a stack allocated object ( and assert when it's the caase ).....


Thanks for your help :)


That is a terrible idea, and your code will crash in horrible, difficult to track down ways down the line.

This topic is closed to new replies.

Advertisement