test to see if object exists with new/delete usage

Discussion in 'C++' started by Squid Seven, Jul 7, 2005.

  1. Squid Seven

    Squid Seven Guest

    I create a pointer to an item:

    CardSession *cardSession;

    Then, later, I use new to create an instance of the item and assign it
    to that pointer:

    cardSession = new CardSession();

    In another function, I want to test if an object is assigned to that
    pointer, and delete the object if that is so:

    if( cardSession )
    delete cardSession;

    I thought this would work, but then I discovered that, if cardSession
    had *ever* been assigned a CardSession object with new, then the if
    statement executes the delete command, even if the object had since been
    deleted. Thus, I sometimes get an item doubly deleted with this code -
    an undefined behavior that I think is causing my program to crash. Note
    that if I have not yet used new in the program to assign an object to
    cardSession, the if statement does not execute.

    Could somebody explain this to me? Am I not understanding pointer usage
    correctly, or is it innapropriate usage of new/delete? How can I do
    this in an efficient fashion, without managing a global pointer to be
    modified everytime I create or delete an object?
     
    Squid Seven, Jul 7, 2005
    #1
    1. Advertisements

  2. Squid Seven

    Squid Seven Guest

    meant to say "without managing a global *flag* to be..." - sorry
     
    Squid Seven, Jul 7, 2005
    #2
    1. Advertisements

  3. I create a pointer to an item:
    Note that the pointer may not have NULL value here.
    This does not test if the pointer points to an object.
    Depends on cardSessions's value obviously. You may explicitly set the
    pointer to NULL initially or after deleting the pointed to object. It's
    safe to call delete cardSession when cardSession==NULL.

    Regards,
    Matthias
     
    Matthias Kluwe, Jul 7, 2005
    #3
  4. Change this to

    CardSession *cardSession = null;

    It's good practice to initialize the variable.
    Yes. Either you don't understand what if(cardSession) does, or you don't
    understand what delete does. For a pointer type such as the variable you
    have here, the conditional

    if(cardSession)

    is a check to see whether cardSession is a null pointer or not--it does
    NOT check if the pointed-to object is valid (and there is no way in
    general to perform such a check in standard C++).

    The subsequent delete statement destroys whatever is pointed to by
    cardSession. If a valid object isn't there, you are likely to crash.

    What you need to do here, and what is also good practice, is to add this
    after you delete:

    cardSession = null;

    Also be aware that your check for whether cardSession is null is not
    necessary. It is perfectly safe to delete a null pointer (but not an
    invalid one), so just

    delete cardSession;
    cardSession=null;

    in place of your original "if" will do the job.

    -cjm
     
    Chad J McQuinn, Jul 7, 2005
    #4
  5. Squid Seven

    Squid Seven Guest

    OK - let me see if I follow... When I create the pointer, if I don't
    initialize it to something, I don't know what it's pointing at - could
    be null, could not be. Then, when I delete the object associated with
    the pointer, while I am indicating that the memory pointed at is
    available for other use, the pointer still points at that memory, until
    assigned to something else, and so causes the if statement to execute
    it's contents?

    Also, if this does not test if the pointer points to an object, how do I
    test for it?

    Thanks for your time Matthias
     
    Squid Seven, Jul 7, 2005
    #5
  6. Squid Seven

    Me Guest

    Unless you overloaded a new operator to have a throw() somewhere, the
    default one doesn't return null on failure, it throws bad_alloc. Also,
    you don't need to check for null when you delete, the delete operator
    does that check for you.
    Ok, I see what you're trying to do. delete is allowed to set the
    pointer to null, but most implementations, like yours, don't do that.
    So you have to explicitly write this as:

    delete cardSession;
    cardSession = 0;

    This doesn't work if you do:

    void foo(Card *c)
    {
    delete c;
    c = 0;
    }

    Card *c = new Card();
    foo(c);
    // c points to garbage instead of null

    You can rewrite that as:

    void foo(Card *&c)
    {
    delete c;
    c = 0;
    }

    and now it will correctly set the c that was passed to foo() to null.
     
    Me, Jul 7, 2005
    #6
  7. Squid Seven

    Squid Seven Guest

    When I try:

    CardSession *cardSession = null;

    I get the error message "'null' was not declared in this scope." Is
    that a compiler-specific issue? Can I simply use:

    CardSession *cardSession = 0;

    as someone else suggested, and still not have to test before calling delete?

    Thanks much for helping out a newbie guys.
     
    Squid Seven, Jul 7, 2005
    #7
  8. Squid Seven

    Squid Seven Guest

    Oh, it was compiler-dependent. I need to use 'NULL', not 'null'.

    All set now, thanks much.
     
    Squid Seven, Jul 7, 2005
    #8
  9. Yes, sorry about that, it should be 'NULL' (not 'null') which should be
    a #define for 0, so those two should be equivalent. This is in C++; in
    plain C, as well as with some older compilers, you might see it #defined
    to something else, such as (void*)0, which causes problems. For this
    reason you'll see a lot of people use a literal zero as you just did. It
    also avoids having to remember if it's NULL or null. :)

    -cjm
     
    Chad J McQuinn, Jul 7, 2005
    #9
  10. OK - let me see if I follow... When I create the pointer, if I don't
    Exactly. You cannot rely on the value of an unitialized variable
    (pointer or not). You cannot rely on a pointer of some type pointing to
    an object of this type (you have to care by yourself).
    As said in the thread, you can assing the value 0 (or NULL if you
    really like to) to indicate no object is pointed to.

    Alternatively, program logic should ensure that some function handling
    the pointer is only called when this makes sense ...

    Regards,
    Matthias
     
    Matthias Kluwe, Jul 9, 2005
    #10
  11. The short answer, hidden in all these replies is: use this idiom:

    CardSession* cardSession = 0;
    ....

    if (cardSession) {delete cardSession; cardSession = 0;}

    Stuart
     
    Stuart MacMartin, Jul 9, 2005
    #11
  12. Squid Seven

    msalters Guest

    Me schreef:
    Actually, it isn't. The pointer being deleted might be const and/or
    volatile, in which case a write would be bad news. Of course, IF the
    ocmpiler can prove it doesn't matter, it might do so - but if it
    provably doesn't matter, why bother?

    Regards,
    Michiel Salters
     
    msalters, Jul 11, 2005
    #12
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.