Re: Question about exceptions.
LR wrote in message...
[snipped code suggestions for main]
I made some but not all of the changes you suggested. Here's the newer
code.
#include <iostream>
#include <exception>
int divide(const int a) {
std::cout << "1 divide(" << a << ")" << std::endl;
if(a == 0)
throw std::exception();
std::cout << "2 divide(" << a << ")" << std::endl;
return 1/a;
}
class X {
int k;
public:
X(const int a)
try : k(divide(a))
{
std::cout << "X(" << a << ")" << std::endl;
}
catch(const std::exception &) {
std::cout << "Caught by X(" << a << ")" << std::endl;
}
};
void test1() {
std::cout << "1 test1()" << std::endl;
try {
X a(1);
X b(0);
}
catch(const std::exception &) {
std::cout << "Caught by test1" << std::endl;
}
std::cout << "2 test1()" << std::endl;
}
void test2() {
std::cout << "1 test2()" << std::endl;
X a(1);
X b(0);
std::cout << "2 test2()" << std::endl;
}
int main() try {
test1();
test2();
}
catch(const std::exception &) {
std::cout << "Caught std::exception & in main" << std::endl;
}
catch(...) {
std::cout << "Caught unknown in main" << std::endl;
}
Here's the output with a comment added for the line I don't quite
understand.
-----------------------------------
1 test1()
1 divide(1)
2 divide(1)
X(1)
1 divide(0)
Caught by X(0)
Caught by test1 // I don't quite get how we got caught a second time
Not sure. I *think* it's because X is not constructed, and you can't return
from an handler [1], the exception needs to follow the chain back to an
handler.
[1]
class X {
// ......
catch( std::exception const &Se) {
// return;
// error: cannot return from a handler of a function-try-block of a
constructor
}
2 test1()
It got to here. The exception was handled by 'test1()' (not passed back to
'main()').
1 test2()
1 divide(1)
2 divide(1)
X(1)
1 divide(0)
Caught by X(0)
Caught std::exception & in main // this is a little confusing too.
There was no handler in 'test2()', so it looks for the next handler, which
it finds in 'main()'.
--------------------------------------
It's the second catch during test1() that I'm confused by. Is that some
compiler magic? A bug? Undefined behavior?
Unless some expert comes by, we may both hang in darkness for the rest of
our C++ lives! <G>
"If an exception does occur, the contained object is not constructed, so
it makes no sense to return to the code that created it. For this
reason, the only sensible thing to do is to throw an exception in the
function-level catch clause."
Some light!
That makes sense, because:
SomeObject x; // If this throws, then...
x.someMethod(); // ...what happens here?
But the standard says in 15 note 3 (I copied this from the 2007 draft,
but the text appears to be the same as the text in the standard.)
"A function-try-block associates a handler-seq with the
ctor-initializer, if present, and the function-body. An exception thrown
during the execution of the initializer expressions in the
ctor-initializer or during the execution of the functionbody transfers
control to a handler in a function-try-block in the same way as an
exception thrown during the execution of a try-block transfers control
to other handlers."
From my understanding, then we get caught and continue on. Perhaps
there's another place in the standard that covers this situation?
Or, they left it to the implementation. Freedom.
So I guess what my example code is doing is a good thing, but is that
what the standard says should happen?
I always thought that once caught, the exception ceased, unless re-thrown.
This seems to be an exceptional (pun?) situation. It kind-of makes sense.
The X object failed to construct, so, the exception can't get fully handled
there.
..
--
Bob R
POVrookie