1

I read that once an exception has been thrown, an object that goes out of scope will be destroyed. So I wrote a code to test it.

#include "stdafx.h"
#include <iostream>
using namespace std;

class E {
public:
    int v = 0;
};

void f() {
    E e;
    E *pointer = &e;
    e.v = 7;
    throw pointer;
}

int main(void) {
    E* MainPointer = new E;
    try {
        f();
    }
    catch (E* e) {
        cout << e -> v; //was executed
        MainPointer = e;
    }
    cout << MainPointer->v; //was executed
    system("pause");
    return 0;
}

The out put was 77, meaning that both the catch block and the final cout was executed. However I was expecting a memory error at the final cout as the object pointed to by MainPointer should have been deallocated by now.

Can someone clarify why the object declared in f() was not deallocated.

Lively
  • 41
  • 6
  • 6
    You are getting Undefined Behavior. Thrown pointer indeed points at some deallocated object, basically it is a dangling pointer. After `MainPointer = e;` assignment `MainPointer` becomes dangling pointer as well (also notice that you leak heap memory). – user7860670 Oct 14 '17 at 15:39
  • Deallocation does NOT, by default, produce memory errors!! There is no guarantee what will happen to the memory pointed to after deallocation, but it is most likely to remain containing the data it did before until it is overwritten. – Jack Aidley Oct 14 '17 at 15:39
  • 5
    Yes, throwing an exception involves something called *stack unrolling* which means all local variables goes out of scope and are destructed. That means that the pointer you catch is invalid, and dereferencing it will lead to [*undefined behavior*](http://en.cppreference.com/w/cpp/language/ub). ***However***, with that said, what's really happening is simply that the memory haven't been reclaimed or otherwise reused yet, so it still retains its old contents. – Some programmer dude Oct 14 '17 at 15:41
  • @Someprogrammerdude wouldn't that work as an answer instead of a comment? – default Oct 14 '17 at 15:44
  • "*the object pointed to by MainPointer should have been deallocated by now*" Why? Did you call `delete` anywhere? – juanchopanza Oct 14 '17 at 15:45
  • You define a destructor that will be called for local variables when an exception is thrown, pointers don't have such destructors. What you are looking for in this case is `std::unique_ptr`, aka unique pointer – Passer By Oct 14 '17 at 15:56
  • Objects are destroyed when they go out of scope, regardless of the reason. – Pete Becker Oct 14 '17 at 15:59

2 Answers2

2

You have two misconception that together created this question. Truth is that

  1. Objects are destroyed when their life span ends according to standard. Auto storage presented by variable declared inside of block is destroyed on exit of block, because standard says so.
  2. You can't check if undefined behavior happens by checking if code works. Undefined behavior includes correct (expected) execution of program.

According to (1) local variable e declared inside of f() was destroyed. According to (2) you can access freed memory and you MAY get proper values. Only way to check if e was destroyed is to define destructor for class E to be able to trace it. Destructor would be called.

Swift - Friday Pie
  • 12,777
  • 2
  • 19
  • 42
0

During exception happens stack unwinding. Object allocated on the stack are destroyed but object allocated on the heap using operator new not. You have to destroy them manually or wrap them to unique_ptr.

Mateusz Drost
  • 1,171
  • 10
  • 23