tags:

views:

406

answers:

8

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!

A: 

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

Paul Betts
+7  A: 

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.

Mark Ransom
Sorry, can you explain more? the function returns false only when an exception occurs, else it will return true. I don't understand why it enters catch block everytime at exactly return false. And then it doesn't really return, because it go to return true later on.
When you're running highly optimized code, the instructions that the CPU is running might not align exactly with the source code, so you'll see some nonsensical results in the debugger.
Mark Ransom
When I change the "return false" statement to an assign statement, there is no error. Is there anything wrong with a return in catch{} block?
return in a catch block is fine. The compiler has emitted some common code between the two return statements. The debug info has to say what source line generated that code, and has opted for the "return false", which means that the debugger is telling you lies when "return true" happens.
Steve Jessop
Oh yes, another possible explanation is that you've modified the source and not recompiled, but I expect that's unlikely.
Steve Jessop
A: 

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

Mr Fooz
I think I'm using debug mode. I set break points and found what I mentioned before.
A: 

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.

David Norman
I run my code under the debug mode, and I placed several break points before throw statement and return false as well as the return true statement. When I debugging my code, I found that return false and return true both reached, but throw never reached.
+2  A: 

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).

CesarB
A: 

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

Patrick
A: 

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.

UberJumper
cerr is exactly like cout. With the exception that it is not buffered (so there is no need to flush it to see the output).
Martin York
@Martin York: you seem to be confusing cout with clog. cout is stdout, while both cerr and clog are stderr (but cerr is unbuffered and clog is buffered).
CesarB
A: 

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;
}
Martin York