Catching all exceptions and logging information - c++

I am a Java programmer working with C++ code, and need some help with exception handling.
I have code in the following structure:
try{
...
}
catch( ... )
{
log("Exception occurred");
}
An exception is occurring, but the try block is really massive and debugging is not an option, so I need to minimally modify the code to give me relevant info on the exception.
So I added the following catch block before the existing catch block (working with my Java knowledge and referring to C++ guides):
catch(exception e)
{
log(e.what());
}
However, I am still getting the old message - "Exception occurred". The code in try block contains a lot of low level functions like strncpy, memcpy etc.
Why is this catch block not working as expected? What can I do to get information on the exception that is occurring and on which line, similar to the stack trace that Java so easily gives.

First, you should catch by reference (generally const), so your new catch block should read:
try {
} catch(std::exception const& e) {
log(e.what());
} catch(...) {
log("Exception occurred");
}
Second, in C++ you may throw any value. Even of type int. If your codebase include such unsavvy throw statements, I pity you.
Since you come from Java, I would check if you mistakenly used a throw new XXXX which would throw a pointer (to a dynamically allocated value) instead of a value. The new is unnecessary in C++.

Probably because those exceptions are not derived from exception class. In C++ any type can be an exception, for example string, int, etc. Anyway if you want to catch exception you should probably catch a reference to the exception &.

You will have to debug and determine if the exception is an C++ exception.
Note that divide by 0 etc are runtime exceptions not supported by C++, so it can be anything literally.
A catch-all handler will only catch valid C++ exceptions not all exceptions(which can be plenty).

Related

Get some information from exception caught with catch(...)? [duplicate]

This question already has answers here:
Is there any way to get some information at least for catch(...)?
(5 answers)
Closed 8 years ago.
I have a try catch clause where the outermost catch(...) never happened until now. After some changes, somewhere an exception which I don't handle with the other cases is thrown. Is there a way to get at least some information about the exception even though I catch it with (...)?
catch (const cone::BeginnersLibException& ex)
{
// handle the exception
}
catch (const std::exception& ex)
{
// handle std exception
}
catch (...)
{
log("Unknown exception caught.");
// How can I get more information about this exception?
}
Edit: here a code snippet that works for me:
#include <cxxabi.h>
// more code here
} catch (...) {
std::string exName(abi::__cxa_current_exception_type()->name());
std::cout<<"unknown exception: "<< exName <<std::endl;
throw;
}
You can do this using gdb or another debugger. Tell the debugger to stop when any exception is throw (in gdb the command is hilariously catch throw). Then you will see not only the type of the exception, but where exactly it is coming from.
Another idea is to comment out the catch (...) and let your runtime terminate your application and hopefully tell you more about the exception.
Once you figure out what the exception is, you should try to replace or augment it with something that does derive from std::exception. Having to catch (...) at all is not great.
If you use GCC or Clang you can also try __cxa_current_exception_type()->name() to get the name of the current exception type.
As a variant on John Zwinck's suggestion to comment out the catch(...) block to let the run-time terminate the application and hopefully provide some more info, you could
catch (...)
{
log("Unknown exception caught in [sensible info here]; will rethrow it");
throw;
}
then you will at least know where in your program the error occured (if there are several possibilities).
One possibility too, on Windows at least, is to write a minidump using MiniDumpWriteDump to get the exception plus stack traces, memory and lots of useful debugging info.
You can use a debugger and enable break on throw, assuming your exceptions really are exceptional this is a good way to know where its coming from.
Also a word of warning should you ever use catch(...) on windows. Under certain build options this will catch SEH exceptions, these are the kinds of things you should never attempt handle such as reading or writing memory out of bounds.
The only way in code (i.e. not using a debugger) to get information from an exception in a catch(...) block is to rethrow the exception, and catch it with specific clauses.
For example.
try
{
// code that might throw something
}
catch (...)
{
try_to_interpret_exception();
}
void try_to_interpret_exception() // we assume an exception is active
{
try
{
throw; // rethrow the exception. Calls terminate() if no exception active
}
catch (std::exception &)
{
// handle all exception types derived from std::exception
// this covers all exceptions that might be thrown by
// the standard C++ library
}
catch (specific_exception &e1)
{
// handle all exception types derived from specific_exception
}
catch (another_specific_exception &e2)
{
// etc
}
}
The catch (so to speak) of this approach is that it requires the programmer to have some knowledge of what the exception might be (e.g. from documentation of a third party library).
|

catch(...) is not catching an exception, my program is still crashing

I'm having a problem with a tester that my application crashes in initialization. I added more logging and exception handling but it still crashes with the generic "this program has stopped working" message rather than triggering my error handling.
Given my main() looks like this and has catch(...) under what circumstances would this not be triggered?
try{
simed::CArmApp app(0, cmd);
for(bool done = false;!done;)
{
done = !app.frame();
}
} catch(const std::runtime_error &e){
handleApplicationError(e.what());
return -1;
} catch(...) {
handleApplicationError("Unknown Error");
return -999;
}
My code is calling into a library doing OpenGL rendering which is where I believe things are going wrong.
If a C++ catch(...) block is not catching errors maybe it is because of a Windows error.
On Windows there is a concept called Structured Exception Handling which is where the OS raises "exceptions" when bad things happen such as dereferencing a pointer that is invalid, dividing by zero etc. I say "exceptions" because these are not C++ exceptions; rather these are critical errors that Windows defines in a C-style fashion - this is because Win32 was written in C so C++ exceptions were not viable.
See also:
Difference between a C++ exception and Structured Exception
try-except Statement
Method of getting a stack trace from an EXCEPTION_POINTERS struct
Update based on comments
If you want both C++ exception handing and SEH perhaps you could try the following (untested) code:
__try
{
try
{
// Your code here...
}
catch (std::exception& e)
{
// C++ exception handling
}
}
__except(HandleStructuredException())
{
// SEH handling
}
If an exception is thrown by the destructor of an object that is destroyed as a result of the stack unwinding to handle a different exception, the program will exit, catch(...) or not.
So far I know, there can be at least two situations where catch(...) cannot actually catch
More than 1 unhandled Exception: when an exception is raised before a previously occurred exception is handled, then c++ can not handle it, and application will crash.
Throwing exception that is not in exception specification list: if any method throws an exception which is not in the exception specification list (in any) then unexpected will be called which calls abort.
Do you declare any global objects?
If you have any objects created outside your main loop, that could explain why it is not caught ( it is not in your try-catch ).

Is it valid to throw in a catch block (C++)?

I haven't done C++ in a while and my memory is fuzzy, nor have I found a definitive answer so far searching. I'm not talking about rethrowing the caught exception, but rather catching one exception and throwing a different type, such as:
std::unordered_map<int, int> foo;
...
int getFoo(int id)
{
try {
return foo.at(id);
}
catch (std::out_of_range& e)
{
throw MyMoreDescriptiveExceptionType();
}
}
Yes. (have to fill to reach 30 characters)
Yes. Among other things, it allows you to log and re-throw exceptions properly.
Just be careful to re-throw properly. If done incorrectly, you could lose the original stack trace which makes the actual problem much harder to track down.
Yes, it's entirely valid. It's actually quite a common thing to do. For example, a small utility class may throw a fairly generic exception. The code that was calling it may catch that exception, and wrap it in a more specific one, providing more useful information about the context. It will then throw that 'outer' exception.
The same catch-wrap-throw pattern can extended as many levels as you need, until something is able to address the problem or shutdown gracefully.
Yes and that thrown exception will be caught by the next catch in order or next upper level catch and so on

Application crashes when throwing an exception

In the application I am writing, I make usage of exceptions for most of my error handling. I've not defined my own exception classes just yet, I merely did the following:
namespace Mage {
typedef std::exception Exception;
}
This way I won't have to change all of my code when I define my own type later which should use the same interface.
That said, any exception crashes my application. Taking the above definition in mind, why would this crash?
void Mage::Root::initialize(Mage::String& p_log) {
// initialize GLFW and GLEW.
if (!glfwInit()) {
throw new Mage::Exception("failed to initialize OpenGL");
return;
} else m_GLFWInitialized = true;
Whether I remove or keep 'new', it would still crash. Am I missing something? I've looked up tutorials but those don't get me any wiser.
I also catch the error right here:
try {
MAGE_ROOT.initialize(Mage::String("Mage.log"));
} catch (Mage::Exception& e) {
std::cerr << e.what() << std::endl;
}
The crash I'm getting is:
Debug Error!
Program: ...sual Studio 2010\Project\Mage3D\Binaries\Debug\Test.exe
R6010
- abort() has been called
(Press Retry to debug application)
The problem is that you are not catching your exception.
I wasn't aware you -have- to catch the exception (from the comments)
Yes, you have to. If you do not catch a thrown exception, std::terminate() will be called. This is the intended behavior: exceptions exist to prevent programmers from forgetting about error handling.
This said, I suggest:
throwing by value;
catching by reference
For instance:
void foo()
{
// ...
throw std::logic_error("Error!");
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Throw by value (std::logic_error derives from std::exception)
// ...
}
void bar()
{
try
{
// ...
foo();
// ...
}
catch (std::exception& e)
^^^^^^^^^^^^^^^
// Catch by reference
{
std::cout << e.what(); // For instance...
}
}
UPDATE:
With regards to the piece of code you posted, you are throwing a pointer and catching by reference. The handler won't match. And since there is no other matching handler, std::terminate() will be called.
Instead, you should throw your exception by value:
throw Mage::Exception("failed to initialize OpenGL");
And if the code you posted is indeed the one you are using, you will see that control is transferred to your handler.
Based on the error message, you're using Visual Studio (2010) for your project. Unless you wrap your throw in a try/catch block, it will "sail through the roof" and be "handled" by the C++ runtime, which means calling abort(). You probably want something like this higher in the call stack:
try
{
SomeFunctionThatUltimatelyThrows();
}
catch(Exception & e)
{
// .. handle error - log, resume, exit, whatever
}
Note also Scott Meyers advice to always catch exceptions by reference. The "exception": If you're using MFC CExceptions though, you want to catch by pointer and call the Delete method for self-destructing heap-based exceptions.
Based on your edit, you may have a mismatch between throwing "by pointer" and catching "by reference". If you've resolved that and are still not getting your catch block to execute, you could try debugging the abort() call by using the CRT SetAbortHandler to install your own abort function. This could simply chain into the existing one, but would give an opportunity to set a breakpoint and examine the call stack to see what is going wrong.
C++ try-catch-throw logic for dummies. Note that this does NOT cover RAII / stack-based allocation / destruction.
When you throw an exception, an exception is said to be "propagating". It propagates up the call stack until it finds the first handler that can handle it (so it's caught) or until it's reached the root of your call stack.
If it is caught, execution continues from the point the exception is caught. The exception is destructed at the end of the catch block.
If it finds the root, it calls std::unhandled_exception, which usually calls std::terminate, which usually calls abort(). In short, everything's dropped ASAP.
If you throw an exception while an exception is currently propagating, you would have two propagating at a time. Java and C# have cutesy ways of dealing with this, but this should never happen in the first place - there's no exception handler that is logically going to handle combinations of exceptions. Do not throw exceptions while one is currently propagating. This rule isn't too hard to hold even if you don't use std::uncaught_exception() which you shouldn't.
While unwinding the stack / propagating the exception all objects found on the stack are destructed. These destructors should never throw an exception - after all, when destroying an object "fails", what else are you going to do after the destructor to fix it?
Always throw by value, catch by reference. If you throw & catch by pointer, you will most likely leak something, which is impossible by reference. If you catch by value, you will slice off your derived exception types. Catch by reference.
At the root of your software, include a catch-all - catch(...). This doesn't allow you to find out what exactly you've caught, but at least you can crash safely. Do this also when the called code may throw "something" that you don't know.

Catch statements are being completely ignored

I've run into a situation with some code I inherited... honestly, I believe the code is written correctly, but this error still seems to manifest.
I'll quickly note that the code is cross-compiled from linux to LynxOS, I'm not sure if that can have anything to do with the error.
Basically, in one specific case:
try {
std::vector<ClassA> x = SomeGeneratingFunction();
//We get to here fine. X may be empty/unpopulated though.
if (x.size() < 1)
{
throw(MyException("It crashed."));
}
}
catch (MyException e)
{
//Handle it.
}
catch (...)
{
//Handle it.
}
We throw given the vector is unpopulated, but for some reason the throw bypasses the catch clauses - both of them. It only seems to happen here - though we woudln't usually do it form an if statement scope, but that should be completely irrelevant since its still in the try scope.
PS: The code below is actually the contents of a function, and exceptions come out of the function when called even though they should all be handled by the catch blocks.
Any ideas how this is possible? And yes, this isn't the real code/exception classes, but the exception class is the simple example you'd google of overloading std::exception, and the SomeGeneratingFunction() does return a good vector, even if it is empty. I cannot provide the real code, but this is exceedingly close barring any little typos I may have made writitng it off the top of my head.
Since the catch (...) clause didn't catch the exception, my answer does not solve the OP's problem. But for others that found this question on SO, maybe my answer is useful, because it explains why the first catch failed.
I had a similar issue where my catch(const std::exception& ex) was just not working. It turned out to be a dumb problem in that I was switching between C# and C++ exceptions, and in C# you need to specify new when you throw your exception, while in C++ you normally don't (but you can, but in this case you are throwing a pointer and not a reference). I was accidentally doing
throw new std::runtime_error("foo");
so
catch(std::exception* ex)
would have caught it but
catch(std::exception& ex)
doesn't. Of course, the solution is just remove the new statement, as that is not the traditional design pattern in C++.
Since you have a spare set of parentheses around the exception object in the throw statement, it looks like a function call. Is there any possibility that you've defined a function called throw? The parameter to the exception constructor keeps this from being a victim of the Most Vexing Parse, but that's a possibility if your actual code differs from your example.
catch (MyException e)
should read:
catch (const MyException &e)
I'm not sure why your throw looks like a function either, kind of bizarre.
Edit:
I've had problems with catches based on something similar, though I agree that it isn't sufficient in this toy case.
The compiler seems off to me, is Try defined as something funny? If it were empty it could make sense if your compiler ignored catch statements with no try.
If you have a function MyException in a smaller scope (possibly even by accident, Most Vexing Parse) then throw MyException("It crashed") will call that function and throw the return value.
Let me slash the problem... Don't use exceptions in C++ unless you want to crash definitely the program. I know exceptions may be quite useful, but they have very poor performances because it raises up an hardware exception which is caught by the operating system kernel. Using return values and error codes can be 500 times faster than throwing and catching exceptions.
I would just rewrite it without using try/catch. Doesn't seem appropriate to use try/catch here anyway. For all you know, exceptions may not work on your target platform.