different behavior of destructor

Discussion in 'C++' started by sacgarg, Mar 23, 2006.

  1. sacgarg

    sacgarg Guest

    Following code is behaving strange:


    class WithPointerMember
    {
    char* str;
    const size_t size;
    public:
    WithPointerMember():size(15) //ctor
    {
    str = new char[size];
    strcpy(str, "Initialized");
    }

    WithPointerMember (const WithPointerMember& other):size(other.size)
    //copy ctor
    {
    str = new char[size];
    for(size_t i=0;i<size;i++)
    str= other.str;
    }

    char* GetString(void) const
    {
    return str;
    }

    ~WithPointerMember() //dtor
    {
    delete [] str;
    }
    };

    Now In main function first I do like
    int main(void)
    {
    WithPointerMember wpm;
    WithPointerMember wpm1 = wpm; <---------- Initializing wpm1 from wpm
    cout<<"string="<<wpm.GetString()<<"\n";
    wpm.~WithPointerMember();
    cout<<"string="<<wpm.GetString()<<endl;
    cout<<"string="<<wpm1.GetString()<<endl;
    return 0;
    }

    The output is expected :

    string=Initialized
    string=
    string=Initialized

    Now I change my main:
    int main(void)
    {
    WithPointerMember wpm;
    cout<<"string="<<wpm.GetString()<<"\n";
    wpm.~WithPointerMember();
    WithPointerMember *wpm1 = new WithPointerMember(); <-------
    Initializing wpm1 from new
    cout<<"string="<<wpm.GetString()<<endl;
    cout<<"string="<<wpm1->GetString()<<endl;
    return 0;
    }

    Here Output is : ( which is not expected )
    string=Initialized
    string=Initialized <------ This is not expected
    string=Initialized

    Can anybody explain that what is going wrong here. I am running code on
    Windows using MSVC compiler

    Thanks.
    sacgarg
     
    sacgarg, Mar 23, 2006
    #1
    1. Advertisements

  2. It's expected, actually. You called the destructor before, which
    deletes WithPointerMember::str. Anything you do afterwards that involve
    the str member can produce anything. Do you really need to call the
    destructor explicitly? And have you considered using std::string?
     
    ferdinand.stefanus, Mar 23, 2006
    #2
    1. Advertisements

  3. sacgarg

    Ben Pope Guest



    Beware, you have not created an operator=, although you are not using it
    here. Prefer:

    WithPointerMember wpm1(wpm);
    OK, this deallocated the internal string.
    Undefined behaviour. You cannot call member functions on destructed
    objects. The rest of the program is useless.
    What do you expect to happen now? wgm and wgm1 will be destructed, you
    cannot call the destructor of an object twice, it invokes undefined
    behaviour.
    Up to here is fine.
    You cannot reasonably expect anything after invoking undefined behaviour.
    wpm has been destructed, more undefined behaviour...
    Stop calling the destructor explicitly. Trust me, you'll never need to.
    What are you trying to achieve?

    Ben Pope
     
    Ben Pope, Mar 23, 2006
    #3
  4. sacgarg

    sacgarg Guest

    calling destructor explicitly is intentional, just to test the
    behaviour.

    I have already read in 'Undefined behaviour in C' that once you free
    the memory, referencing it again can give you anything.

    Is it same here?
     
    sacgarg, Mar 23, 2006
    #4
  5. sacgarg

    sacgarg Guest


    Thanks for mentioning that, but I was aware that I am not going to use
    it.
    Here by calling destructor explicitely, I am not destructing object
    itself, instead I am deleting the internal string, then how come object
    is destructed? I am confused.
    This is intentional for testing the behaviour of pointer member.
     
    sacgarg, Mar 23, 2006
    #5
  6. sacgarg

    Ben Pope Guest

    In real code, you should declare it private and not implement it.
    Attempts to use it will be caught by the compiler.
    You are destructing the object, the compiler may be doing some other
    background stuff that you are not aware of. It is as free to do this,
    as it is to implement it's own constructor, destructor, copy constructor
    and assignment operator if you do not provide one.

    In that destructor you deallocate the internal buffer. One of the
    invariants of your object is that the internal buffer exists. Take a
    look at the member functions, they all assume that str points to a valid
    char[] (GetString may be able to get away with a NULL str). Therefore,
    having str point to a valid char[], or NULL is an invariant.
    Well, after invoking undefined behaviour, your tests are meaningless.

    Ben Pope
     
    Ben Pope, Mar 23, 2006
    #6
  7. sacgarg

    Rolf Magnus Guest

    Yes you are. Guess why it is called "destructor".
    When an object is created, two things happen:

    - raw memory is acquired
    - a constructor is used to turn that raw memory into an object

    After the destructor was executed, you can't expect an object anymore. It is
    now back to raw memory.
     
    Rolf Magnus, Mar 23, 2006
    #7
    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.