CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 14 of 14
  1. #1
    Join Date
    Jan 2000
    Posts
    129

    How to find out if the object is dynamic and was created on the heap?

    I have a pointer to an object and I need to call delete operator only if the object was created on the heap. Is there any way to programmatically define this?

    I'm using MFC in my app.

    Thanks for your help.

  2. #2
    Join Date
    Apr 1999
    Posts
    27,449

    Re: How to find out if the object is dynamic and was created on the heap?

    Originally posted by olstar
    I have a pointer to an object and I need to call delete operator only if the object was created on the heap. Is there any way to programmatically define this?
    No.

    Why not let the module that allocated the pointer be responsible for deleting the pointer?

    Regards,

    Paul McKenzie

  3. #3
    Join Date
    Nov 2002
    Location
    California
    Posts
    4,556
    If you're working with objects of a class you authored, then include a member variable like m_bCreatedOnHeap. Set it to your preferred default in the ctor, and then override it in your code when the object is created (if it's created inconsistently with the default).

    Then, in the dtor, test for its value and condition a "delete this;" on it:
    Code:
    class CMyClass{
    ...
    BOOL m_bCreatedOnHeap;
    ...
    };
    
    CMyClass::CMyClass() : m_bCreatedOnHeap(TRUE)
    {
    ...
    }
    
    CMyCLass::~CMyCLass()
    {
    if (m_bCreatedOnHeap) delete this;
    }
    
    // in code
    
    CMyClass cmy;
    cmy.m_bCreatedOnHeap=FALSE; // must overrride since it's on the stack
    
    CMyClass* pcmy = new CMyClass; // default is ok as it is
    HTH,
    Mike

  4. #4
    Join Date
    Jul 2002
    Posts
    107
    Hi,

    First for Mike:
    If you dynamically allocate the class, how will the destructor get called so it can delete itself? If you call delete on the ptr there will be a stack overflow since delete calls the destructor inside the destructor, so if its dynamically allocated, it will call the destructor over and over...

    The best solution for this to to overload the delete operator for the class.

    Do as mike suggested and put a boolean in the class.
    also in the class do this:

    Code:
    class ...{
    public:
    .
    .
    void operator delete(void* obj);
    };
    
    void CMyClass::operator delete(void* obj){
        CMyClass* delObj = (CMyClass*)obj;
        if(!delObj){
            return;
        }
    
        if(delObj->m_bCreatedOnHeap){
            free(delObj);
        }
    }
    
    void main(){
        CMyClass* ptr = new CMyClass;
    
        delete ptr;
    
        CMyClass static;
        ptr = &static;
    
        delete ptr;  // calls the same delete function, won't free memory
    }
    this way you can call delete on any pointer and it will only delete those with the flag set.

    operator delete in a class is a static function so you can't reference any member variables, thats why you have to do the cast.

    Hope this helps.
    Last edited by oktronic; September 29th, 2003 at 06:08 PM.

  5. #5
    Join Date
    Apr 1999
    Posts
    27,449
    But in general, there is no way to determine that, if given a pointer, whether it points to a dynamically created object. This is well explained with a whole chapter dedicated to this in Scott Meyers "More Effective C++".

    Maybe the OP should tell us what they are trying to accomplish and why determining whether an object was or was not created dynamically needs to be done. Usually, doing such things are a sign of a bad design.

    Regards,

    Paul McKenzie

  6. #6
    Join Date
    Feb 2000
    Location
    San Diego, CA
    Posts
    10,354
    I agree .. When one tries to do such thing and sees that the only solution to do that is such hacks, there is some problem somewhere and things start getting ugly.

    I would say the same about runtime class information too.

    It would be a good exercise to try to avoid it as much as possible. You may end up in a neater version..

  7. #7
    Join Date
    Jul 2002
    Posts
    107
    The only problem with doing things like this "hack" as you call it, otherwise known as overloading the delete operator, is that it makes the code too confusing for most out there, run-time type identification is also confusing for most.
    However there are more then enough reasons to use these things in your programs. COM is a good example of why you need RTTI. Granted I'll give Paul credit here cause COM is awfully designed.
    Polymorphism and operator overloading is a necessity though in many application and many do not realize how much easier their lives would be it they would just buckle down and learn it instead of fearing what they don't understand.
    Its the deference between makeing 6 figures and only 5, so its worth the time...

  8. #8
    Join Date
    Nov 2002
    Location
    California
    Posts
    4,556
    Originally posted by oktronic
    First for Mike:
    If you dynamically allocate the class, how will the destructor get called so it can delete itself? If you call delete on the ptr there will be a stack overflow since delete calls the destructor inside the destructor, so if its dynamically allocated, it will call the destructor over and over...
    Of course you're correct. The destructor would not be called and if it were there would be a terrible recursion (if indeed it was possible to call the destructor more than once considering that the "this" pointer would be invalid).

    Rather than overloading the delete operator, however, it might be better to define a member function called something like DeleteMeIfNeeded(), which could be called on any object. It also makes sense to check the "this" pointer, so you might have code like
    Code:
    void CMyClass::DeleteMeIfNeeded()
    {
    if(this!=NULL && m_bCreatedOnHeap) delete this;
    }
    I seem to recall that this is the technique used in MFC to pass CException's by pointer, and to ensure that the CExceptions are deleted if needed, and a check at http://www.microsoft.com/msj/0799/c/c0799.aspx by Paul DiLAscia confirms this.

    I also agree that it's getting awfully close to a hack.

    -Mike

    edit: I just remembered that the debug version sets "this" to something odd like 0xCDCDCDCD, so the check against NULL won't work.
    Last edited by MikeAThon; September 29th, 2003 at 07:33 PM.

  9. #9
    Join Date
    May 1999
    Location
    Southern California
    Posts
    12,266
    I agree that it is better to not need to determine whether an object was allocated on the stack or the heap and to either not delete itself or delete itself based on where it has been allocated.

    Note that many MFC classes have a m_bAutoDelete member that determines whether the object deletes itself.
    "Signature":
    My web site is Simple Samples.
    C# Corner Editor

  10. #10
    Join Date
    Sep 2002
    Location
    Maryland - Fear The Turtle!
    Posts
    7,537
    Originally posted by MikeAThon

    edit: I just remembered that the debug version sets "this" to something odd like 0xCDCDCDCD, so the check against NULL won't work.
    it's not odd It's the debug CRT at work.
    Code:
    static unsigned char _bCleanLandFill  = 0xCD;   /* fill new objects with this */

  11. #11
    Join Date
    Jul 2002
    Posts
    107
    Hi Mike,

    (if indeed it was possible to call the destructor more than once considering that the "this" pointer would be invalid).
    The destructor is the first thing called when you delete, so the "free" would never be reached to invalidate the pointer.

    While I have no idea why this guy wishes to do this, there are reasons that you might wish do check something like this.

    I can think for several, but I'll give you a quick breakdown of one that popped in my head.
    you have a std::map.
    You have a dynamic list passed back from some obnoxious "windows" like api function which expects you to delete the memory it allocated...
    You have a bunch of static objects that you wish to sort and operate on with the returned dynamic ones.

    you put them in your map and run a loop to operate on them...
    you then have to run another loop and operate on those aswell...
    The performance is dropped by the second loop, especially if you need to a windows pump so it doesn't lock up your program. Cause both loops will need it if you have length operations or millions of elements...
    Then you need to delete the memory which is another loop which also requires a "anti-locking" mechinism if there a lots of elemets.

    if you approach the problem the same way this guy is, then you can delete each of the elements after you operate on them all in the same loop, so there is no need for the second or third loop.
    While you say "but the performance hit is minimal", sure it is, for only 1000, maybe 10000 but on 1000000? 100000000? you can save time by deleteing them as you go. And since the sorted list has pointers for both, you don't have to worry about whether it was a static or dynamic with this approach.

    Its not a hack, just a performance boost, it cuts a little un-necessary fat out of your program. If you make very intensive programs as I do, then you need to cut these chunks out so your program doesn't look like something MS made...

    However, I have no idea why he's doing it this way, such things may not be necessary for him and in someways may slow him down... hopefully he'll find another way.
    Last edited by oktronic; September 29th, 2003 at 07:48 PM.

  12. #12
    Join Date
    Nov 2002
    Location
    California
    Posts
    4,556
    Hi oktronic:

    OK, you convinced me and I'm back on the non-hack side And although MFC perhaps shouldn't be held up as an example, as Sam points out there are many MFC classes that have a m_bAutoDelete member that determines whether the object deletes itself (other than the CException class I originally mentioned).

    It would be nice to hear from the OP.

    -Mike

    PS to mick_2002: I suppose that "odd" was a poor choice of words <g>

  13. #13
    Join Date
    May 1999
    Location
    Southern California
    Posts
    12,266
    I don't remember anyone mentioning "Smart" pointers but that is probably another solution.
    "Signature":
    My web site is Simple Samples.
    C# Corner Editor

  14. #14
    Join Date
    Nov 2003
    Location
    Austria
    Posts
    1
    See the attached gobal function IsDynamic(void* pPointer), which returns true if the pPointer was created on the heap. The idea is to get a pointer to the heap start and compare it to pPointer. In Visual C++ 5.0 the stack memory allways lies below the heap memory.
    The function _heapwalk(...) in <malloc.h> allows you to get a pointer to the first heap element. In IsDynamic(...) these two pointers are compared and thats all.

    Comments to your problem:
    ===================
    As described in all other comments above I believe that it is a very bad programming style what you are doing. Normally you should know when to use dynamic or static object. The only usefull usage of IsDynamic(...) is to ensure that only dynamic pointers are added to another object handling and destroying them. This was the only reason for me to develop this check, but maybe it will solve your problem too.
    Attached Files Attached Files

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured