I have seen too many people trying to determine if an object is allocated on the heap or not. It can help to create a garbage collection or find if an object with a reference counter should automatically call the
delete operator or not when its counter reaches zero.
You can search in the web for many articles dealing with this but most of them have the problem that they rely on how the memory is initialized or they aren't thread safe.
But with the help of thread local storage that the operating system provides and a very rarely used stuff that MFC has, we can deal with this problem easily. MFC gives us some classes to store information private for each thread with the
THREAD_LOCAL macro (you can see more in afxtls.cpp and afxtls_.h in the MFC source code). So taking advantage of this macro I created an internal class that is used when the object is constructed and when it is allocated on the heap, by overriding the
new operator of the base class initializes the internal detector of the thread that is currently allocating the object if it was not done previously and then sets a flag indicating that the object is being allocated on the heap. Later, when the constructor is called, the base class checks if this flag is on or not to determine if the object is on the heap or not.
Using the code
The only thing you must do to detect if your objects are allocated dynamically or not is to derive them from
CDynamicObjectBase and then call the
IsAllocatedOnDynamicMemory function anywhere you wish.
To use the code in your project, add the DynamicObjectBase.cpp and DynamicObjectBase.h files to your project and add
CDynamicObjectBase as a base class for your classes.
class yourg_class : public CDynamicObjectBase
In the sample application you will see a class named
CMyCustomObject that has a function that prints where it was allocated.
- To make the code MFC-independant you must create a copy of the functionality of most classes and functions located in afxtls_.h and afxtls.cpp. I did it and it is not difficult for an experienced programmer.
- There is a function named
DynamicObjectBaseReset that resets the internal state of the detector in the thread context of the caller. I didn't test what happens if an exception is thrown during the object's constructor. I think nothing happens because
CDynamicObjectBase's constructor is called before any derived constructors (it is the base class), or you can modify the code to catch exceptions, but for any case the function is provided.
As a final note, suggestions for improvements are welcome.