A strange problem with C++ exception handler - c++

I used standard exception handling methods in C++. Which is try{} and catch{} block. In my code, func1() would throw an exception, And func2 is like this:
bool func2()
{
try{
func1();
}
catch(myException& e)
{
cerr << "error!" << endl;
return false;
}
return true;
}
But when I run my code, a strange thing happens. I never reached the code of throwing the exception, but I always reached the line of return false in catch block (but the line of cerr << is never reached either). Then the function continue to return true. I don't know what the reason is. Can anyone help me to figure the problem out? Thank you very much!

If you're using any optimize flags in your compiler (i.e. not debug mode), you can't trust the debugger to show you the proper lines of execution. You've made contradictory statements - the "return false" statement is executing, but the function is returning true. This is the only explanation I can think of.

As #Mark Ransom said, you are probably with optimization enabled. To help you understand what is goind on, this is the C++ equivalent of the code the compiler is probably generating:
bool func2()
{
bool ret;
try{
func1();
ret = true;
}
catch(myException& e)
{
cerr << "error!" << endl;
ret = false;
}
return ret;
}
However, when you are at the return ret; "line" on the generated code, there are two lines in the original code you could actually be in: return false; and return true;. The debugger has no idea which is the correct one, and so it displays the first one (actually, it is the compiler when generating the tables the debugger will use which makes the choice).
This will be much more obvious if you tell the compiler to generate an assembly file and look at it. Assuming this is x86, where the return value is on %eax, both branches will be setting %eax to either 1 or 0 and then jumping or falling through to the common function epilogue code (which is where it will actually return from the function).

Open your app in WinDbg (or gdb), and enable first chance exceptions (in WinDbg via sxe eh).

How do you know it reached the return false? If func2 didn't do the cerr and returned true, it sounds like no exception was caught and the return false wasn't executed.
If you are using a debugger, sometimes it will show that you are on the closing brace for the catch block when no exception is thrown, which might be confusing.

If you're hitting the return true statement is another type of exception being thrown? Try adding a catch(...).

I've noticed sometimes cerr can act werid, have you tried replacing the cerr with a cout? Also just try putting two cout's within the exception block.

If no output is being produced and the function is RETURNING true.
Then no exception is escaping func1().
As a result the function returns true.
But what you may be experiencing is the de-buggers inability to map machine instructions back to C++ source after the code has been optimized (as the optimizer may re-arrange the code).
I suggest you try somthing like the below to make sure you are reporting all exceptions.
Try this:
bool func2()
{
try
{
func1();
}
catch(MyException const& e)
{
std::cerr << "Error!: Cought My Exception\n";
return false;
}
catch(...) // Catch any other exceptions
{
std::cerr << "Error!: Unknown Exception detected\n";
/*
* To keep the same functionality of your original code
* Rethrow the unknown exception.
*/
throw;
}
return true;
}

Use Debug mode, not optimized mode. Also, make sure that you aren't writing to any dangling pointers.

Related

What does throw do when not in used with try and catch?

What does throw do when not used with try and catch? Like:
if (IsEmpty()) throw "Stack is empty, Cannot delete";
Does it get printed in console?
But when throw contains some int or char as its arguments, it is thrown to catch; what happens in this case?
The C++ runtime will have something along the lines of (this is NOT exactly how it looks, but you can think of it as working this way, unless you are working on something very special):
void BeforeMain()
{
try
{
int res = main();
exit(res);
}
catch(...)
{
cout << "Unhandled exception. Terminating..." << endl;
terminate();
}
}
You are allowed to do that, and it will not be caught anywhere within your code if you have not put an explicit try catch block.
Windows uses a SEH mechanism to handle , where you could have an uncaught exception filter to figure out about the same
See this post for more details
Catching exceptions thrown without try/catch

What could be overriding the return code from main()?

I have a rather odd occurrence happening that I haven't been able to nut out yet.
I have test case that is supposed to catch errors and return the appropriate error code from main, but /sometimes/ on test runs the program returns 0 even when the error code is non zero.
The exception class thrown is:
class exit_request {
public:
explicit exit_request(int code = 0) : m_code(code) {}
int code() const { return m_code; }
private:
int m_code;
};
The test case code is:
int main(int argc, char* argv[])
{
try {
// Do some test case stuff
// Eventually, due to the supplied command line arguments,
// we expect an exit_request() to be thrown from within
// library code.
}
catch (exit_request& exp) {
std::cout << "Exit Request:" << exp.code() << std::endl;
return exp.code();
}
catch (std::exception& err) {
std::cout << "Error: " << err.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
In many runs of this test case, everything works as expected: The exit_request() exception is thrown, caught, exp.code() is printed (its value is 2), and the return code from the process is 2.
However, very occasionally, the return code from the process is 0 (i.e. no failure), even though exp.code() is printed as 2.
Can anyone help explain a situation in which this can occur? i.e. the return value from main is changed from non-zero to zero before the process exits?
This is occurring on Windows 7 (x64), with MSVC++ 2010 Express, building a x86 (32-bit) application. I have not seen this odd failure on any of our other Windows or Linux platforms, or compilers, but that doesn't necessarily mean it couldn't happen in those environments.
If you have any atexit handlers that call exit(0), or any static-storage-duration objects whose destructors do that, it might explain what you're seeing. They get executed after your return statement. It's undefined behavior, which could explain why you only see it happen sometimes.
Maybe you are not throwing the exception correctly...
I mean that from the function called or processing done in try block, you are throwing exception of some other type.
Try to write a default catch block for that.

Is this C++ code defining main or running main?

I'm reading Stroustrup's Programming: Principles and Practice and came across this code:
int main()
try {
// our program
return 0; //0 indicates success
}
catch (exception& e) {
cerr << "error: " <<e.what() <<'\n';
keep_window_open();
return 1; // 1 indicates failure
}
catch (...) {
cerr << "Oops: Unknown exception!\n";
keep_window_open();
return 2; //2 indicates failure
}
At first I thought that the first line called the main function (which contained the heart of the code and was written somewhere else). And then we are just trying to catch errors that might have occurred inside of main(). But if that's the
case, why does it say "our program" in the try block? This makes me think that
this code is defining main(). But if that's the case, then where are the bracket
s? That is, why isn't it int main() { on the first line?
int main()
try
{
}
catch (...)
{
}
...optionally more catches...
...is just a shorter notation equivalent to...
int main()
{
try
{
}
catch (...)
{
}
...optionally more catches...
}
Why does it exist? Well:
As soon as you see the function, you understand that a try/catch block encompasses all the function content, whereas in the second form you have to scan down to the end to see if there's anything after the catches. This insight makes it quicker and easier to reason about the exception handling.
With the second notation, another programmer's more likely to unwittingly insert code before or after the try/catch block, which may invalidate earlier exception handling design. A try/catch block makes it more obvious that "encompassing" exception handling is a deliberate design decision.
It's more concise.
If you have an existing function and want to add exception handling to it, then using the function try block notation clearly avoids having to indent everything inside the function to continue to comply with normal indentation practices. Indenting an entire function is painful, especially if you observe an 80 (or whatever) character line length and have to manually wrap long lines to get them formatted the way you want. (Similarly, if you had a catch statement then decide to let the exceptions directly reach the caller - obviously more useful for functions other than main - you can remove the try/catch without needing to unindent the try { } content.)
It defines the main() function using function-try-block:
When is a function try block useful?

Catching expection from nested function doesn't work

I've got a class cnMeshHelper whose method cnMeshHelper::initialize calls various functions that may throw cnZeroDivisionException.
The stripped down code looks like this:
cnVector cnVector::getNormalized() {
if (getLength() == 0.0) {
#ifdef DEBUG
printf("Throwing exception in cnVector::getNormalized().\n");
#endif // DEBUG
throw cnZeroDivisionException();
}
// ...
}
cnMatrix cnMatrix::getNormalized() {
return cnMatrix(
T.getNormalized(),
B.getNormalized(),
N.getNormalized(),
M.getNormalized() );
}
cnMatrix cnComputeTangentSpace( /* ... */ ) {
cnMatrix mat;
// ...
mat.T = mat.T.getNormalized()
return mat;
}
void cnMeshHelper::initialize(cnMesh& mesh) {
// ...
polygonMatrix = cnComputeTangentSpace( /* ... */ );
}
int main() {
cnMesh* mesh = new cnMesh( /* ... */ );
// ...
try {
cnMeshHelper helper;
helper.initialize(*mesh);
}
catch(cnZeroDivisionException& e) {
cout << "Zero division exceptione caught.\n";
}
}
Now, in some cases, it can happen that the cnMesh* mesh has invalid values that cause to throw an exception in cnVector::getNormalized().
But the problem is, if this is the case, the try-catch clause does not catch the exception. The program just terminates after printing the DEBUG-text in the method above.
Update: Note that I can catch the exception within cnMeshHelper::initialize() but everything "outer" doesn't work.
Even using catch(...) does not work in the main.
Can you tell me why the exception isn't caught ?
Got it !
It happens often, that the issue lies somewhere else. So in this case, too.
The cnMeshHelper destructor throwed a null-pointer because of an uninitialized member. The member was uninitialized because of the cnZeroDivisionException in cnMeshHelper::initialize.
Thanks for you help, anyway.
The part
catch(cnZeroDivisionException& e) {
will catch exactly one kind of exception. But what happens if there is another exception or a non-exception abort (dereferencing NULL, ...)?
So please move the printf into the if sections to see if really an exception of the right type is thrown.
My crystal ball guess is that getLength will reveal something bad since you wrote
...it can happen that the cnMesh* mesh has invalid values...
These invalid values might affect getLength also in some way. (nullpointers, uninitialized memory, other exceptions, ...)
Got it !
It happens often, that the issue lies somewhere else. So in this case, too.
The cnMeshHelper destructor throwed a null-pointer because of an uninitialized member. The member was uninitialized because of the cnZeroDivisionException in cnMeshHelper::initialize.
Thanks for you help, anyway.
Does any of the functions involved have exception specifications (void fn() throw(some_exception))? They will abort the program if an exception that doesn't match the specification is thrown.
I repeat the previous advice of stepping through the code with a debugger.

ellipsis try catch on c++

Can an ellipsis try-catch be used to catch all the errors that can lead to a crash? Are there are any anomalies?
try
{
//some operation
}
catch(...)
{
}
No, it'll only catch C++ exceptions, not things like a segfault, SIGINT etc.
You need to read up about and understand the difference between C++ exceptions and for want of a better word, "C-style" signals (such as SIGINT).
If the code inside try/catch block crashed somehow, the program is anyway in a non-recoverable state. You shouldn't try to prevent the crash, the best that the program can do is just let the process crash.
The "anomaly" is in the fact that your code only catches the exceptions, and not the errors. Even if the code is exception-safe (which may be not the case, if you are trying to work-around its mistakes by a try/catch block), any other inner error may bring the program into irrecoverable state. There is simply no way to protect the program from it.
Addition: look at this article at "The Old New Thing" for some insights.
It is the Catch All handler.
It catches all the C++ exceptions thrown from the try block. It does not catch segfault and other signals that cause your program to crash.
While using it, You need to place this handler at the end of all other specific catch handlers or it all your exceptions will end up being caught by this handler.
It is a bad idea to use catch all handler because it just masks your problems and hides the programs inability by catching all(even unrecognized) exceptions. If you face such a situation you better let the program crash, and create a crash dump you can analyze later and resolve the root of the problem.
It catches everything that is thrown, it is not limited to exceptions. It doesn't handle things like windows debug asserts, system signals, segfaults.
TEST(throw_int) {
try {
throw -1;
} catch (std::exception &e) {
std::cerr << "caught " << e.what() << std::endl;
} catch (...) {
std::cerr << "caught ..." << std::endl;
}
}
Throwing an integer isn't really recommended though. It's better to throw something that inherits from std::exception.
You might expect to see something like this as a last ditch effort for documenting failure, though. Some applications aren't required to be very robust. Internal tools might cost more than they are worth if you went through the paces of making them better than hacked together crap.
int main(int argc, char ** argv) {
try {
// ...
} catch (std::exception &e) {
std::cerr << "error occured: " << e.what() << std::endl;
return 1;
}
return 0;
}