How can I know the name of the exception in C++? - c++

With Python, I could get the name of the exception easily as follows.
run the code, i.e. x = 3/0 to get the exception from python
"ZeroDivisionError: integer division or modulo by zero" tells me this is ZeroDivisionError
Modify the code i.e. try: x=3/0 except ZeroDivisionError: DO something
Is there any similar way to find the exception name with C++?
When I run the x = 3/0, the compiled binary just throws 'Floating point exception', which is not so useful compared to python.

While you can't easily ask for the name of the exception, if the exception derives from std::exception you can find out the specified reason it was shown with what():
try
{
...
}
catch (const std::exception &exc)
{
std::err << exc.what() << std::endl;
}
On a side note, dividing by 0 is not guaranteed to raise a C++ exception (I think the MS platforms may do that but you won't get that on Linux).

If you want to know the name of the exception class, you could use RTTI. However, the vast majority of C++ code will throw an exception derived from std::exception.
However, all you get is the exception data contained in std::exception::what, and you can get the name of the exception class from RTTI and catch that explicitly if you need more information (and it contains more information).

For most exceptions if you have the RTTI option set in your compiler, you can do:
catch(std::exception & e)
{
cout << typeid(e).name();
}
Unfortunately the exception thrown by a divide by zero does not derive from std::exception, so this trick will not work.

If this is a debugging issue, you may be able to set your compiler to break when it hits an exception, which can be infinitely useful.

Related

How to get from exceptions to user error messages

When we learn in school user data validation is most often blatantly ignored. I taught myself to validate data with the exception mechanism, but when I try to print useful user messages it feel very clumsy to do that from the exceptions. The more I try the more I feel like exceptions are meant for "inside the code", and they should not "escape" to the end user.
Let's take a simple example. The user needs to enter a command. The format can be: cmd i j or cmd with cmd a predefined set of commands and i and j numbers. We then execute that command.
What I have, from bottom to up is this:
// utility function, converts string to enum
str_to_enum(string str, map<enum, string> s) -> enum
// may throw std::invalid_argument{"cannot convert " + str + " to enum"}
parse_line(string line)
tokens = split(line)
Cmd cmd = tokens[0]; // calls str_to_enum, lets the exception pass by
if (tokens.empty())
throw std::invalid_argument{"empty string as command"s};
if (...)
throw std::invalid_argument{cmd.spelling() + " does not take any argument."};
if (...)
throw std::invalid_argument{cmd.spelling() + " takes exactly 2 arguments."};
str_to_int(tokens[1])
str_to_int(tokens[2]) // throws std::out_of_range
main_loop() {
get_line(line);
try {
Full_cmd full_cmd = line; // calls parse_line, may throw
if (...)
throw std::invalid_argument{"Coordinates out of range"};
try {
execute_cmd(full_cmd); // may throw
}
catch (std::exception& e) {
cerr << "error executing command:" << endl;
cerr << e.what() << endl << endl;
}
}
catch (const std::exception& e) {
cerr << "Invalid command '"s << line << "': " << endl;
cerr << e.what() << endl;
}
}
I think the above logic can be easily followed.
Now, if I want to just display the cryptic "Invalid command" and "Error executing command" then all would be easy. But I want meaningful messages, like the ones I tried above. One problem is that e.what doesn't feel the proper vesel for this. It contains succinct, often technical details. Another problem is that for instance the error "cannot convert <input_string> to enum" reaches the user. While he gets the real string he input, the enum part is implementation detail and criptic for him.
What I see are 2 solutions:
Use std::exception errors.
catch errors at almost any step and rethrow with a reworked message. E.g. from "Cannot convert to enum" to "Command not found".
At the topmost level catch std::exception and basically print e.what()
create exception classes for each type of error (e.g. invalid_command, invalid_no_args etc..
If necessary add more information (other data members) to it in order to have the complete context of the error
once an exception is thrown, it bubbles up to the topmost level
Then at the top-most level, catch each custom exception type and print accordingly.
I obviously went with the first approach. The big downside are the imperfect messages the user gets.
For the second one I feel there is a disproportionate effort vs gain. There would be a lot of boring redundant work just to create the custom exception classes. I tried it once and gave up after the 7'th almost identical class each fully equipped custom data members and constructors and what methods (that set and use those members)
Also, couldn't help but feel I'm reinventing the wheel.
My question is: are exceptions solely a good tool to convey error messages to the end user? If so what is the right way of doing it? If not, how can it be done?
The first approach is not the right approach, for two reasons:
As you have witnessed, it represents a tremendous amount of work.
It presumes that programmers may possibly manage to code into an exception object an error message that could potentially be meaningful to a user. They can't; It wouldn't. If not for any other reason, then at least because statistically speaking, the language in which the programmers will write the message is unlikely to be a language understood by the user. (And I mean this primarily from a linguistic standpoint, though the "level of technicality" standpoint is also worth considering.)
The second approach is in the right direction, but with some modifications:
Drastically reduce the number of exceptions that your system may throw by preemptively checking for mistakes and presenting error messages like "I will not allow you to do this" instead of messages like "what you did was bad, and it failed".
Drastically reduce the number of exception classes that you have to define at each level of your system by making each exception simply stand for "failed to [do whatever this level was trying to do] because such-and-such exception was thrown by a level below". By storing a reference of the "causal" exception into the new exception, you save yourself from having to write lots of new exceptions at each level, with lots of member variables etc.
Realize that human-readable error messages inside exceptions are completely useless: never write such a message, and never show such a message to the user. The message of an exception is the class name of the exception. If you have RTTI, (Run-Time-Type-Information,) use it. Otherwise, just make sure that each exception object knows the name of its own class. This is for your eyes only, and when you see it, you know unambiguously which exception it is.
At the top level of your system, only display error messages to the user about exceptions that you can test. Yes, this means that you have to be able to set up your system so that the exception will actually be thrown, so that your testing code can make sure that the exception was caught and the right error message was issued.
For exceptions that you cannot test, do not even bother showing a message. Just display a general-purpose "something went wrong" error, (along with a nice humorous image perhaps,) and append as much information as you can to your application's log, for your forensic analysis later.
TL;DR
My question is: are exceptions solely a good tool to convey error messages to the end user? If so what is the right way of doing it? If not, how can it be done?
Yes, exceptions are solely meant to convey error/exeptional conditions to the client.
They are not meant to introduce any program control flow in conjunction with catch() or final statements.
The big downside are the imperfect messages the user gets.
You have many options to provide useful messages using the std::runtime_error exception.

Why are my C++ exceptions not being caught?

I have some C++ code that uses a very standard exception pattern:
try {
// some code that throws a std::exception
}
catch (std::exception &e) {
// handle the exception
}
The problem is that the exceptions are not being caught and I cannot figure out why.
The code compiles to a static library in OS X (via Xcode). The library is linked into a Cocoa application, with a call to the function in question happening via an Objective-C++ thunk. I suspect that the interplay between Objective-C and C++ is the culprit but all my attempts to pin this down have failed.
I have not been able to create a simple example that reproduces this behavior in a simple example. When I take the relevant code out of the context of my big program everything works.
Can anyone suggest why my exceptions are not being caught?
C++ allows you a variety of options for catching: value, reference or pointer.
Note that this code only catches std::exceptions passed by reference or value:
try {
// some code that throws a std::exception
}
catch (std::exception &e) {
// handle the exception
}
It's likely that the exception is being passed by pointer:
catch (std::exception* e)
Check the code that is throwing the exception, and see how it's doing it.
As Mark points out, if you catch by value instead of by reference you risk slicing your object.
Try a catch(...) {} block, see if an exception is really thrown.
I suspect that the interplay between Objective-C and C++ is the culprit but all my attempts to pin this down have failed.
You're probably right, although it's hard to track down.
First, GCC explicitly does not allow you to throw exceptions in Objective C++ and catch them in C++ ("when used from Objective-C++, the Objective-C exception model does not interoperate with C++ exceptions at this time. This means you cannot #throw an exception from Objective-C and catch it in C++, or vice versa (i.e., throw ... #catch).")
However, I think you're describing a case where Objective C++ calls C++ code, the C++ code throws and you're hoping for C++ code to catch the exception. Unfortunately I'm having difficulty finding documentation for this specific case. There is some hope because, "It is believed to be safe to throw a C++ exception from one file through another file compiled for the Java exception model, or vice versa, but there may be bugs in this area." If they can do it for Java, there is a chance they can do it for Objective C++.
At the very least, you'll need to specify -fexceptions at compile time ("you may need to enable this option when compiling C code that needs to interoperate properly with exception handlers written in C++"). Again, that doesn't specifically mention Objective C++ but it may apply.
One little known gotcha with exceptions relates to the access of the base class.
If you are actually throwing a class that derives privately from std::exception then the std::exception handler will not be chosen.
For example:
#include <iostream>
class A { };
class B : private A { } ;
int main ()
{
try
{
throw B ();
}
catch (A & )
{
std::cout << "Caught an 'A'" << std::endl;
}
catch (B & )
{
std::cout << "Caught an 'B'" << std::endl;
}
}
Usually, such an order of handlers would result in the 'B' handler never being selected, but in this case 'B' dervies from 'A' privately and so the catch handler for type 'A' is not considered.
I can offer two theories:
the exception gets caught before it comes your catch clause; any function on the stack might be the culprit. As Michael proposes, try catching everything.
exception unwinding fails to locate your handler. To analyze this in more detail, you would have to step through the exception unwinding code, which is very hairy. See whether compiling the Objective-C code with -fobjc-exceptions helps.
This might be a long shot, but in Visual Studio's compiler settings there is an option to switch off exceptions entirely. Perhaps there's something similar in GCC / XCode.
C++ exceptions can be just about anything, quite frequently a char*. As suggested before add catch (...) to at least get it to break and see what's going on.
Thanks for the input from everyone. Those are good suggestions for anyone who runs into a similar problem. It's working now, but I'm not 100% sure which of various changes I made caused things to become sane again. Once again, the approach of simplifying down to something that works and building back up from there paid off.
One thing that wasn't mentioned in the responses, and which I think was part of my confusion, is to make sure that the handler makes it obvious that it actually caught the exception. I think that in some of my formulations of the handler it was masking that fact and passing the exception on to a higher level handler.

C++ retrieve exception information

I have a c++ dll which I need to debug. Due to the circumstances in which I am using the dll, I am unable to debug it via the calling application.
So, I created a try -catch, where the catch writes the exception to a file.
The line which needs to be debugged involves imported classes from a 3rd party dll, so I have no way of knowing what type of exception it is. When I tried catch(exception e), no message was written to the file. So I tried catch(...), which did trigger something:
using std::exception::what, the only thing that got written to the file was "1".
using std::exception::exception, the file received the following code : "0579EF90".
Is there any way for me to retrieve meaningful info about the exception that was thrown?
TIA
CG
If you don't use catch(KnownExceptionType ex) and use your knwoledge about KnownExceptionType to extract info, no you can't.
When you catch with catch(...) you are pretty much lost, you know that you handled an exception but there is no type information there, there is little you can do.
You are in the worse case, an exception coming out from a library, you have no info on the exception, even if you had headers for the lib, that exception type doesn't need to be defined there.
If I understand you correctly, you've already narrowed down the source of the issue to a specific call to a 3rd party library, but you're not allowed to debug the application live (do I want to ask why?), and your question is "how can I debug the exception without any knowledge of what the exception is"
The answer is, you can't. As you observed, you can blindly guess and hope to catch the right thing. You can also catch(...), but that will tell you exactly nothing. If you could debug live, you could set the debugger to break when the exception is thrown and see what is going on there.
I think the right answer though is to contact the 3rd party library you've narrowed down the source of the issue to and ask them. It is very, very bad form to throw an exception and allow it to propogate across module boundries. It makes me suspect that it's a Windows SEH exception for a null pointer deref or something, and you're compiling in such a way that catch(...) catches those.
maybe try catching std::exception & e
std::cout << e.what() << endl;
see if you can cast it to std::logic_error, and std::runtime_error - that should give you some clue what you're dealing with
Firstly, you should always catch exceptions by const reference, in other words:
catch( const std::exception & ex ) {
...
}
Not doing so means that your exceptions will be of the exact type you catch and this may result in the loss of exception information.
However, it seems that your library is throwing something not derived from std::exception - you need to find out what the type (ideally the base type) is.
I'm a bit confused. On the one hand you write catch(std::exception) didn't work (you should use catch(const std::exception&), BTW), on the other hand you also write you invoked std::exception::what(). How did you do this if you didn't have a std::exception in the first place?
Anyway, once you have caught anything but ..., you could try to log the RTTI info:
#include <typeinfo>
try {
foreign_code(my_data);
} catch(const some_type& x) {
std::cerr << "Yikes! Caught exception of type '"
<< typeid(x).name()
<< "' with its hand in the cookie jar!\n";
std::abort();
}
While the standard doesn't make any assumptions of the result of std::type_info::name(), most (if not all) compilers will generate code that emits something that's at least somewhat useful.
When you're inside the VS debugger, you could also set it up so that it will stop at any exceptions thrown. That gives you a stack trace and thus might give you a clue as to what data passed to the DLL could have cause the problem.

Can't catch exception!

I'm using swig to wrap a class from a C++ library with python. It works overall, but there is an exception that is thrown from within the library and I can't seem to catch it in the swig interface, so it just crashes the python application!
The class PyMonitor.cc describes the swig interface to the desired class, Monitor.
Monitor's constructor throws an exception if it fails to connect. I'd like to handle this exception in PyMonitor, e.g.:
PyMonitor.cc:
#include "Monitor.h"
// ...
bool PyMonitor::connect() {
try {
_monitor = new Monitor(_host, _calibration);
} catch (...) {
printf("oops!\n");
}
}
// ...
However, the connect() method never catches the exception, I just get a "terminate called after throwing ..." error, and the program aborts.
I don't know too much about swig, but it seems to me that this is all fine C++ and the exception should propagate to the connect() method before killing the program.
Any thoughts?
You have to forward the exceptions to Python if you want to parse them there.
See the SWIG Documentation.
In order to forward exceptions, you only have to add some code in the SWIG interface (.i) file. Basically, this can be anywhere in the .i file.
All types of exceptions should be specified here, and SWIG only catches the listed exception types (in this case std::runtime_error, std::invalid_argument, std::out_of_range), all other exceptions are caught as unknown exceptions (and are thus forwarded correctly!).
// Handle standard exceptions.
// NOTE: needs to be before the %import!
%include "exception.i"
%exception
{
try
{
$action
}
catch (const std::runtime_error& e) {
SWIG_exception(SWIG_RuntimeError, e.what());
}
catch (const std::invalid_argument& e) {
SWIG_exception(SWIG_ValueError, e.what());
}
catch (const std::out_of_range& e) {
SWIG_exception(SWIG_IndexError, e.what());
}
catch (...) {
SWIG_exception(SWIG_RuntimeError, "unknown exception");
}
}
I'm not familiar with swig, or with using C++ and Python together, but if this is under a recent version of Microsoft Visual C++, then the Monitor class is probably throwing a C structured exception, rather than a C++ typed exception. C structured exceptions aren't caught by C++ exception handlers, even the catch(...) one.
If that's the case, you can use the __try/__except keywords (instead of try/catch), or use the _set_se_translator function to translate the C structured exception into a C++ typed exception.
(Older versions of MSVC++ treated C structured exceptions as C++ int types, and are caught by C++ handlers, if I remember correctly.)
If this isn't under Microsoft Visual C++, then I'm not sure how this could be happening.
EDIT: Since you say that this isn't MSVC, perhaps something else is catching the exception (and terminating the program) before your code gets it, or maybe there's something in your catch block that's throwing another exception? Without more detail to work with, those are the only cases I can think of that would cause those symptoms.
It's possible that a function called directly or indirectly by the Monitor constructor is violating its exception specification and doesn't allow std::bad_exception to be thrown. If you haven't replaced the standard function for trapping this, then it would explain the behaviour that you are seeing.
To test this hypothesis you could try defining your own handler:
void my_unexpected()
{
std::cerr << "Bad things have happened!\n";
std::terminate();
}
bool PyMonitor::connect() {
std::set_unexpected( my_unexpected );
try {
_monitor = new Monitor(_host, _calibration);
} catch (...) {
printf("oops!\n");
}
}
If you get the "Bad things have happened!" error message then you have confirmed that this is the case, but unfortunately there may not be a lot that you can do. If you're 'lucky', you may be able to throw an exception from my_unexpected that is allowed by the exception specification of the function that is currently failing, but in any case your unexpected handler is not allowed to terminate normally. It must throw or otherwise terminate.
To fix this you really need to get into the called code and either correct it so that the exception specification is not violated, either by fixing the specification itself or by fixing the code so that it doesn't throw the exception that isn't expected.
Another possibility is that an exception is being thrown during stack unwinding caused by the original exception being thrown. This also would cause termination of the process. In this case, although you can replace the standard terminate function, you have no option but to abort the program. A terminate handler isn't allowed to throw or return, it must terminate the program.

C++ catching all exceptions

Is there a c++ equivalent of Java's
try {
...
}
catch (Throwable t) {
...
}
I am trying to debug Java/jni code that calls native windows functions and the virtual machine keeps crashing. The native code appears fine in unit testing and only seems to crash when called through jni. A generic exception catching mechanism would prove extremely useful.
try{
// ...
} catch (...) {
// ...
}
will catch all C++ exceptions, but it should be considered bad design. You can use c++11's new current_exception mechanism, but if you don't have the ability to use c++11 (legacy code systems requiring a rewrite), then you have no named exception pointer to use to get a message or name. You may want to add separate catch clauses for the various exceptions you can catch, and only catch everything at the bottom to record an unexpected exception. E.g.:
try{
// ...
} catch (const std::exception& ex) {
// ...
} catch (const std::string& ex) {
// ...
} catch (...) {
// ...
}
Someone should add that one cannot catch "crashes" in C++ code. Those don't throw exceptions, but do anything they like. When you see a program crashing because of say a null-pointer dereference, it's doing undefined behavior. There is no std::null_pointer_exception. Trying to catch exceptions won't help there.
Just for the case someone is reading this thread and thinks he can get the cause of the program crashes. A Debugger like gdb should be used instead.
This is how you can reverse-engineer the exception type from within catch(...) should you need to (may be useful when catching unknown from a third party library) with GCC:
#include <iostream>
#include <exception>
#include <typeinfo>
#include <stdexcept>
int main()
{
try {
throw ...; // throw something
}
catch(...)
{
std::exception_ptr p = std::current_exception();
std::clog <<(p ? p.__cxa_exception_type()->name() : "null") << std::endl;
}
return 1;
}
and if you can afford using Boost you can make your catch section even simpler (on the outside) and potentially cross-platform
catch (...)
{
std::clog << boost::current_exception_diagnostic_information() << std::endl;
}
try {
// ...
} catch (...) {
// ...
}
Note that the ... inside the catch is a real ellipsis, ie. three dots.
However, because C++ exceptions are not necessarily subclasses of a base Exception class, there isn't any way to actually see the exception variable that is thrown when using this construct.
it is not possible (in C++) to catch all exceptions in a portable manner. This is because some exceptions are not exceptions in a C++ context. This includes things like division by zero errors and others. It is possible to hack about and thus get the ability to throw exceptions when these errors happen, but it's not easy to do and certainly not easy to get right in a portable manner.
If you want to catch all STL exceptions, you can do
try { ... } catch( const std::exception &e) { ... }
Which will allow you do use e.what(), which will return a const char*, which can tell you more about the exception itself. This is the construct that resembles the Java construct, you asked about, the most.
This will not help you if someone is stupid enough to throw an exception that does not inherit from std::exception.
In short, use catch(...). However, note that catch(...) is meant to be used in conjunction with throw; basically:
try{
foo = new Foo;
bar = new Bar;
}
catch(...) // will catch all possible errors thrown.
{
delete foo;
delete bar;
throw; // throw the same error again to be handled somewhere else
}
This is the proper way to use catch(...).
it is possible to do this by writing:
try
{
//.......
}
catch(...) // <<- catch all
{
//.......
}
But there is a very not noticeable risk here: you can not find the exact type of error that has been thrown in the try block, so use this kind of catch when you are sure that no matter what the type of exception is, the program must persist in the way defined in the catch block.
You can use
catch(...)
but that is very dangerous. In his book Debugging Windows, John Robbins tells a war story about a really nasty bug that was masked by a catch(...) command. You're much better off catching specific exceptions. Catch whatever you think your try block might reasonably throw, but let the code throw an exception higher up if something really unexpected happens.
Let me just mention this here: the Java
try
{
...
}
catch (Exception e)
{
...
}
may NOT catch all exceptions! I've actually had this sort of thing happen before, and it's insantiy-provoking; Exception derives from Throwable. So literally, to catch everything, you DON'T want to catch Exceptions; you want to catch Throwable.
I know it sounds nitpicky, but when you've spent several days trying to figure out where the "uncaught exception" came from in code that was surrounded by a try ... catch (Exception e)" block comes from, it sticks with you.
Well, if you would like to catch all exception to create a minidump for example...
Somebody did the work on Windows.
See http://www.codeproject.com/Articles/207464/Exception-Handling-in-Visual-Cplusplus
In the article, he explains how he found out how to catch all kind of exceptions and he provides code that works.
Here is the list you can catch:
SEH exception
terminate
unexpected
pure virtual method call
invalid parameter
new operator fault
SIGABR
SIGFPE
SIGILL
SIGINT
SIGSEGV
SIGTERM
Raised exception
C++ typed exception
And the usage:
CCrashHandler ch;
ch.SetProcessExceptionHandlers(); // do this for one thread
ch.SetThreadExceptionHandlers(); // for each thred
By default, this creates a minidump in the current directory (crashdump.dmp)
Be aware
try{
// ...
} catch (...) {
// ...
}
catches only language-level exceptions, other low-level exceptions/errors like Access Violation and Segmentation Fault wont be caught.
A generic exception catching mechanism
would prove extremely useful.
Doubtful. You already know your code is broken, because it's crashing. Eating exceptions may mask this, but that'll probably just result in even nastier, more subtle bugs.
What you really want is a debugger...
Can you run your JNI-using Java application from a console window (launch it from a java command line) to see if there is any report of what may have been detected before the JVM was crashed. When running directly as a Java window application, you may be missing messages that would appear if you ran from a console window instead.
Secondly, can you stub your JNI DLL implementation to show that methods in your DLL are being entered from JNI, you are returning properly, etc?
Just in case the problem is with an incorrect use of one of the JNI-interface methods from the C++ code, have you verified that some simple JNI examples compile and work with your setup? I'm thinking in particular of using the JNI-interface methods for converting parameters to native C++ formats and turning function results into Java types. It is useful to stub those to make sure that the data conversions are working and you are not going haywire in the COM-like calls into the JNI interface.
There are other things to check, but it is hard to suggest any without knowing more about what your native Java methods are and what the JNI implementation of them is trying to do. It is not clear that catching an exception from the C++ code level is related to your problem. (You can use the JNI interface to rethrow the exception as a Java one, but it is not clear from what you provide that this is going to help.)
For the real problem about being unable to properly debug a program that uses JNI (or the bug does not appear when running it under a debugger):
In this case it often helps to add Java wrappers around your JNI calls (i.e. all native methods are private and your public methods in the class call them) that do some basic sanity checking (check that all "objects" are freed and "objects" are not used after freeing) or synchronization (just synchronize all methods from one DLL to a single object instance). Let the java wrapper methods log the mistake and throw an exception.
This will often help to find the real error (which surprisingly is mostly in the Java code that does not obey the semantics of the called functions causing some nasty double-frees or similar) more easily than trying to debug a massively parallel Java program in a native debugger...
If you know the cause, keep the code in your wrapper methods that avoids it. Better have your wrapper methods throw exceptions than your JNI code crash the VM...
If you are looking for Windows-specific solution then there is structured exception handling:
https://learn.microsoft.com/en-us/cpp/cpp/try-except-statement
The code looks as follows
__try
{
// code here may throw or make access violation
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
// after exception code here, e.g. log the error
}
It will catch not only C++ exceptions but also access violations or other system exceptions.
Well this really depends on the compiler environment.
gcc does not catch these.
Visual Studio and the last Borland that I used did.
So the conclusion about crashes is that it depends on the quality of your development environment.
The C++
specification says that catch(...) must catch any exceptions, but it doesn't in all cases.
At least from what I tried.