Answering a recent question on exceptions, reminded me of an old query.
The following compiles in c++
#include <iostream>
using namespace std;
struct weird {
void danger()
{
throw *this;
}
};
int main()
{
weird object;
object.danger();
return 0;
}
Yet it always results in runtime error.
Isn't the object thrown, preserved during stack unwinding?
The runtime error smells like a call to terminate
, how is this caused?
If weird object
was declared in an enclosing scope (the global here) could this work in an inner scope? (where unwinding that stack wouldn't affect superior ones?)
A ball thrown upwards falls back towards the surface of Earth due to force of gravity. The force of gravity is a force.
Gravitational force of the earth acts on every object having mass. When an object is thrown upwards the gravitational force of the earth acts against the velocity of the object and pulls the object downwards, i.e, towards itself. thus the object returns back towards the earth.
The result is a call to std::terminate()
because the exception is never caught. Change it to the following and it works fine:
int main() {
weird object;
try {
object.danger();
}
catch (weird &w) {
std::cout << "caught weird\n";
}
}
- Isn't the object thrown, preserved during stack unwinding?
When an exception is thrown, the exception throwing mechanism makes a copy of the thrown value into some private memory somewhere, so the lifetime of the 'thrown' object does not matter.
(Of course if you throw a pointer then the pointer value is preserved, not the pointed-to object. In that case you must ensure that catch handlers do not do illegal things with the pointer value, either by ensuring the object still exists, or that the catch handler does not deference the pointer.)
- The runtime error smells like a call to
terminate
, how is this caused?
When an exception is thrown and there is no corresponding catch handler C++ states that std::terminate()
must be called. The exception throwing mechanism responsible for finding an appropriate catch handler implements this by calling std::terminate()
when it fails to find an appropriate catch handler.
- If
weird object
was declared in an enclosing scope (the global here) could this work in an inner scope?
Whether it's global or not doesn't matter; the behavior of throwing the exception is (mostly) well defined either way.
(One thing that's implementation specified is if the stack gets unwound before std::terminate()
is called when no catch handler is found. I believe that on most implementations the stack is not unwound in this case.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With