deleting stack objects?


DevX Home    Today's Headlines   Articles Archive   Tip Bank   Forums   

Results 1 to 9 of 9

Thread: deleting stack objects?

  1. #1
    Join Date
    Apr 2005
    Posts
    4

    Question deleting stack objects?

    I have a simple question. Im currently learning C++, I am an experienced C# and Java programmer and have a need to write some lower level programs, so decided to learn C++.

    Heres the source code to my problem and my question is below.

    ----------------------Source Code------------------------------------------
    #include <iostream>
    using namespace std;
    class Counter
    {
    public:
    Counter();
    Counter(int num);
    ~Counter();
    int GetVal() const { return this->cnt; }
    void SetVal(int newNum);

    private:
    int cnt;
    };

    Counter::Counter(int num): cnt(num){}
    Counter::~Counter() { cout << "DESTRUCTOR CALLED" << endl; }
    void Counter::SetVal(int num)
    {
    this->cnt = num;
    }

    int main()
    {
    Counter myCnt(6);
    cout << "My Cnt Value = " << myCnt.GetVal();
    myCnt.SetVal(7);
    cout << endl << "Count now = " << myCnt.GetVal() << endl;
    Counter *pMyCnt = &myCnt;
    cout << "The address of my count is: " << pMyCnt << " and the value is: " << pMyCnt->GetVal() << endl;
    pMyCnt->SetVal(888);

    cout << "The pointer object value is: " << pMyCnt->GetVal() << endl;
    cout << "The original object value is: " << myCnt.GetVal() << endl;

    try
    {
    delete pMyCnt;
    pMyCnt = 0;
    cout << "Object Pointed used to delete object." << endl;
    cout << "So can we now access it? " << pMyCnt->GetVal() << endl;
    }
    catch(...)
    {
    cout << "Deleting the object through the pointer succeed." << endl;
    }

    try
    {
    myCnt.SetVal(777);
    cout << "Trying to access the original reference to Counter: " << myCnt.GetVal() << endl;
    cout << "The address for myCnt is: " << &myCnt << endl;
    }
    catch(...)
    {
    cout << "Failed.. the objection no longer exists." << endl;
    }

    return 0;
    }
    ----------------------End Source Code--------------------------------------

    The problem I have is I use the pointer for Counter to delete the Counter object, yet when I use the Counter variable myCnt later on it still works.

    Now the pointer is supposed to delete the object from my understanding and the output says it does as the object deconstructor is called. So why then can I still use the object with myCnt?

    What am I missing here?

  2. #2
    Join Date
    Dec 2003
    Posts
    3,366
    Thats not really a pointer, its a 'reference'. You took the address of a variable which exists on the stack, and while you can modify the contents and do things with the address, you can't delete it this way because its not dynamically allocated. The delete on this address is a mistake, its undefined behavior (your compiler seems to have handled this safely, at least today). 'Stack' or local variables exist until they go out of scope.

    To dynamically allocate, you would have
    pmyCnt = new Counter; //get it dynamically
    ...
    delete pmyCnt; //ok, now after this line, if you access it, it should crash.

  3. #3
    Join Date
    Apr 2005
    Posts
    4

    Ahh thanks.

    Ahh thanks for the answer. That clears it up.

    Thanks for the answer.

    Cheers

  4. #4
    Join Date
    Nov 2003
    Posts
    4,118
    Your code results in undefined behavior which means that anything can happen, and that it's behavior is unpredictable. The problem is that you're calling delete to destro an object that was allocated on the stack. Such objects never get deleted explicitly -- they are destroyed automatically.
    Another note: you try blocks don't contain any throw statements so their matching catch() blocks never execute. To test catch() blocks you need to throw an execption from inside the try block.
    Danny Kalev

  5. #5
    Join Date
    Apr 2005
    Posts
    4
    Thanks Danny for the insight into the Try Catch statements.

    I hadnt actually gotten to that yet in my learning and was going off my C# background. I just skipped ahead in the text book to see what the syntax was to catch all exceptions.

    The first catch block seems to execute when I run the code, however wont work when running in DEBUG mode. I have to compile it in release mode for it to work. I have yet to learn why that is so and guess Ill find out when I get to error handling.

    Cheers

  6. #6
    Join Date
    Apr 2005
    Posts
    4
    One last thing. If you compile that code using VS 2003 you will see that even though Im trying to delete the object off the stack, the deconstructor is still called.

    That could lead to some nasty problems as well especially if you allocate memory in your object and then free it up in the deconstructor.

    Cheers

  7. #7
    Join Date
    Nov 2003
    Posts
    4,118
    Quote Originally Posted by Agent_Smith
    Thanks Danny for the insight into the Try Catch statements.

    I hadnt actually gotten to that yet in my learning and was going off my C# background. I just skipped ahead in the text book to see what the syntax was to catch all exceptions.

    The first catch block seems to execute when I run the code, however wont work when running in DEBUG mode. I have to compile it in release mode for it to work. I have yet to learn why that is so and guess Ill find out when I get to error handling.

    Cheers
    Don't sweat too hard: the fact that the catch(...) gets called occasionally is due to a long standing bug in Visual C++. The catch(...) should *never* get called if there is no explicit throw statement in your try block.
    Generally speaking, notice that that exceptions are a losse term that means different things. In C++ parlance, an exception occurs if and only if a throw statement is executed in the program. However, there is another type of "exception" called Structured Exception Handling which is something quite different. Sadly, Microsoft messed things up a few years ago by letting C++ exceptions constructs "interact" with SEH. This is going to be fixed in Visual C++ 2005 (at last!). To summarize, the catch() statements in yoru code are unreachable code.
    Danny Kalev

  8. #8
    Join Date
    Nov 2003
    Posts
    4,118
    Quote Originally Posted by Agent_Smith
    One last thing. If you compile that code using VS 2003 you will see that even though Im trying to delete the object off the stack, the deconstructor is still called.

    Cheers
    Which is exactly what "undefined behavior" means: expect the unexpected. I'm not surprised thet destructor (that's the correct technical term) is called: the compiler assumes that the stack object terminates its life like a normal stack object, i.e., by having its destructor called when the object goes out of scope. I suspect that what yoru code does is essentially corrupt the process's heap.
    Anyway, imagine what would happen if the destructor did more serious resource releasing operations such as closing files or closing sokcets, database connections etc.
    Danny Kalev

  9. #9
    Join Date
    Dec 2003
    Posts
    3,366
    Debug and release modes can do some strange things -- they are so different its hard to point to any one thing and say 'this is why it works in debug and not in release'

    The fastest way to see a difference is compile with a assembler output (listing file?) and see what the options did to the assembler code that makes one version work and another different. The slow way is to transform a debug into a release one option at a time.

    Thats one way to do undefined things, to call the destructor... the problem is not how the compiler handled undefined operations so much as that it "worked". Whenever wrong code works some of the time, you can be fooled into thinking its just a bug in your code. Its far better that wrong code does not work or even compile, but because of complexity, this cannot always be done by a compiler. Here, to catch the problem, the compiler has to "know" that the pointer points to a local variable instead of a dynamic object, which requires too much knowledge on the compiler's part -- imagine you assign (pointers a and b) a = b; -- and b is a pointer to a local object, as you have -- now the compiler has to know 2 deep that a is a pointer to a reference... how many deep should it look? Almost all of the undefined behaviors in the language are like this (too hard to detect as errors).

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center
 
 
FAQ
Latest Articles
Java
.NET
XML
Database
Enterprise
Questions? Contact us.
C++
Web Development
Wireless
Latest Tips
Open Source


   Development Centers

   -- Android Development Center
   -- Cloud Development Project Center
   -- HTML5 Development Center
   -- Windows Mobile Development Center