Home > Enterprise >  Why exception not the same when catching exception pointer?
Why exception not the same when catching exception pointer?

Time:09-21

I'm new to C exception handling. I tried to throw an exception pointer and caught it but it seems the later caught exception isn't the same as which I thrown. Here's my code:

try {
    bad_exception e2 = bad_exception();
    cout << e2.what() << endl;
    cout << &e2 << endl;

    throw &e2;
}
catch (bad_exception* ex) {
    cout << ex << endl;
    cout << ex->what() << endl;
    cout << (*ex).what() << endl;
}

output:
bad exception
00CFFCF8
00CFFCF8
Unknown exception
Unknown exception

I'd expected the later will show the same name "bad exception". Can you explain this?

updated:
It seems the exception has the "auto delete" feature? I tried throwing a pointer to normal object (not inherited from exception). But I can still access the object and its properties in the catch block.

try {
    char str[5] = "eed8";
    A a = A();
    a.name1 = str;

    cout << a.show() << endl;
    cout << &a << endl;

    throw &a;
}
catch (A* exp) {
    cout << exp << endl;
    cout << exp->show() << endl;
    cout << exp->name1 << endl;
}

output:
eed8
007BF9DC
007BF9DC
eed8
eed8

CodePudding user response:

You should throw exceptions by value (usually).

The problem here is you are throwing a pointer to an object. Unfortunately, by the time the pointer is caught, the object that it is pointing to has been destroyed, and thus you have an invalid pointer.

try {
    bad_exception e2 = bad_exception();
    cout << e2.what() << endl;
    cout << &e2 << endl;

    throw &e2;
}  // At this point the object "e2" goes out of scope
   // Thus its destructor is called.
   // So the pointer you threw now points at an invlalid object
   // Thus accessign the object via this pointer is UB.

catch (bad_exception* ex) {
    cout << ex << endl;
    cout << ex->what() << endl;
    cout << (*ex).what() << endl;
}

Rewrite it like this:

try {
    bad_exception e2 = bad_exception();
    cout << e2.what() << endl;
    cout << &e2 << endl;

    throw e2; // Throw a copy.
              // Throw an object that gets copied to a secure location
              // so that when you catch it is still valid.
}
catch (bad_exception const& ex) {  // catch and get a reference to the copy.
    cout << &ex << endl;
    cout << ex.what() << endl;
}

If you absolutely must throw a pointer, then use new to make sure the pointer has a dynamic life span (but remember, you will need to clean it up).


Update:

It seems the exception has the "auto delete" feature?

Not a thing.

I tried throwing a pointer to normal object (not inherited from exception).

There is nothing special about the exception object (or any of its derived classes). It is simply a normal object. Like all objects (that are a class), the destructor of the object is run when the object reaches the end of its lifetime. If A does not have a destructor then the memory used by the object may not change (but it is not usable by other objects that are not your object).

But I can still access the object and its properties in the catch block.

That is the bad side of "Undefined Behavior". I may look like it is working. It's not working, it just looks like it is. And it is just as likely to not work on some other situation.

  • Related