326

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.

Trevor Hickey
  • 36,288
  • 32
  • 162
  • 271
Obediah Stane
  • 15,471
  • 14
  • 39
  • 28
  • 1
    Same as [How to build a C++ Dll wrapper that catches all exceptions?](http://stackoverflow.com/questions/541235/how-to-build-a-c-dll-wrapper-that-catches-all-exceptions) – lsalamon Jan 12 '11 at 13:22
  • 4
    Note that most crashes are not caused by exceptions in C++. You can catch all exceptions, but that won't prevent many crashes. – Mooing Duck Jul 07 '16 at 22:16
  • What you may be looking for if you ended up here: https://stackoverflow.com/a/32799720/1599699 https://www.man7.org/linux/man-pages/man2/sigaction.2.html https://www.man7.org/linux/man-pages/man7/signal.7.html – Andrew Nov 10 '20 at 05:21

16 Answers16

396
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 (...) {
    // ...
}
Adam Miller
  • 1,756
  • 1
  • 25
  • 44
Greg D
  • 43,259
  • 14
  • 84
  • 117
  • 78
    It is a good practice to catch exceptions by const reference. As in: catch(std::exception const & ex) { /* ... */ } – coryan Nov 25 '08 at 01:18
  • 6
    @coryan, Thanks for the reminder. I've been spending too much time in C# land lately. :) – Greg D Nov 25 '08 at 01:51
  • 16
    @coryan: Why is it good practice to catch by const reference? – Tim MB Nov 09 '12 at 17:01
  • 26
    Avoiding unnecessary copies is one benefit. – Greg D Nov 10 '12 at 21:59
  • 31
    -1: the suggestion that this will "catch all exceptions in C++" is misleading. Try generating a divide by zero error inside the try block. You will see that it will generate an exception that is not caught, yet the code is clearly in C++. It would be more helpful to state that this will "catch all C++ exceptions" and then add some mention of structured exceptions to the notes on limited usefulness. – omatai Feb 05 '13 at 01:57
  • 48
    @omatai: Fixed, it will catch all C++ exceptions. Division by zero is undefined behavior and does not generate a C++ exception. – Mooing Duck Feb 28 '13 at 23:24
  • 12
    @omatai It may seem misleading, but it is still accurate. Dividing by zero raises a signal; it does not throw an exception. The two are different, and the language has terminology for both. – Trevor Hickey Jan 14 '16 at 15:09
  • 8
    But you can use the Windows `__try {} __except()` to catch all exceptions, even hardware signals that would normally crash your application. Check https://msdn.microsoft.com/en-us/library/s58ftw19.aspx and https://msdn.microsoft.com/en-us/library/ms681409(v=vs.85).aspx – TheRealChx101 Feb 19 '16 at 14:54
  • 7
    Ah, but this was a question about C++, not about platform-specific extensions. – Greg D Feb 19 '16 at 21:02
  • When using the ```...``` syntax, how do I get a reference to the thing I caught so I can print it or read its fields or learn its type? What type could the caught thing have, if not ```std::exception``` or ```std::string```? Which other types are throwable in c++? – dinosaur Aug 17 '16 at 21:45
  • 1
    @dinosaur: The answer covers your question. If you're using an older flavor of C++, you get no reference to the thrown object (which, btw, could be of any type. C++ does not limit throwable types: https://isocpp.org/wiki/faq/exceptions#what-to-throw). If you're using a newer flavor of C++, you might be able to leverage current_exception: http://www.cplusplus.com/reference/exception/current_exception/ . – Greg D Aug 17 '16 at 22:03
  • 3
    @TimMB Another major benefit is that it doesn't cause your exception object to be sliced, so that virtual functions like `what()` actually work. – C. K. Young Dec 15 '16 at 17:41
  • @dinosaur the reason to nest the `catch` blocks like this is to get a workable type for the exception object. C++ requires variable types to be known at compile time, and there's no uber-class that can be used as the parent type for every exception; `std::exception` is the closest but as you can see it isn't universal. The biggest problem I've seen is with Microsoft's MFC library, which supported exceptions before `std::exception` was part of the language, so it throws a *pointer* to class `CException`. – Mark Ransom Mar 21 '19 at 17:39
  • Is it ok to to `catch (...)` if you do `throw;`? – Moberg Jun 16 '22 at 15:22
  • @Moberg I was surprised to find out it does not catch in this case. – foxesque Apr 22 '23 at 17:36
180

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.

Donald Duck
  • 8,409
  • 22
  • 75
  • 99
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • 4
    Well, as Shy points out, it is possible with the VC compiler. It's not a good idea, but it is possible. – Shog9 Nov 25 '08 at 01:25
  • 7
    yeah with SEH. but not with sane standard c++ techniques :) well if you stick to windows you can nearly do everything :) – Johannes Schaub - litb Nov 25 '08 at 02:08
  • 1
    Mmm... thanks for this tidbit. I've been looking for the answer as to why my null-pointer exceptions aren't beeing caught! –  Aug 20 '09 at 11:15
  • 11
    You can catch segfaults with SEH on Windows and signal(2)/sigaction(2) on POSIX systems, which covers that vast majority of systems in use today, but like exception handling, it's not something that should be used for normal flow control. It's more of a "do something useful before dying." – Adam Rosenfield Oct 11 '09 at 16:03
  • 1
    @AdamRosenfield until you have implemented `try { .. } catch(...) { ... }` for catching using signal/sigaction, i wouldn't call it "catching" :) If in a signal handler, it's relatively hard for the programmer to know where in the code the crash happened (i'm talking about programmatically detecting that), compared to try/catch. – Johannes Schaub - litb Apr 22 '14 at 21:01
  • One can use `_set_se_translator` to catch structured exceptions on Windows as C++ exceptions. This includes read/write access violation, stack overflow and division by zero. – 4LegsDrivenCat Dec 28 '19 at 19:16
  • what is difference between `catch(...)` vs `catch(std::exception)`? – Mayur Nov 12 '20 at 11:00
  • That's correct, but sometimes we can catch a sigabort which also causes a crash if we do not take an immediate action like a graceful termination. – Maf Mar 16 '23 at 12:17
108

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;
}
bobah
  • 18,364
  • 2
  • 37
  • 70
  • 2
    what is difference between `catch(...)` vs `catch(std::exception)`? – Mayur Nov 12 '20 at 11:00
  • 2
    In C++ you can throw anything, an `int` for instance. `...` would catch that too. You “should” catch exceptions by `const&`, btw. – bobah Nov 12 '20 at 15:26
  • FYI, in vs2015, "boost::current_exception_diagnostic_information()" just returns "No diagnostic information available." even with debug information available. – Javanator Dec 18 '20 at 16:05
  • 3
    I'm pretty sure that `p.__cxa_exception_type()->name()` isn't going to be portable. In fact, I just tried it with clang and it wouldn't compile. – Edward Falk Aug 20 '21 at 02:46
  • @EdwardFalk - the first sentence of the answer explicitly says "GCC", so - dah – bobah Aug 20 '21 at 08:45
  • When using `catch (...)`, the body of the catch should either do `throw;` to re-throw the exception after e.g. logging it, or terminate the program altogether (e.g. `std::terminate()`). Unless one knows how to handle an exception, one should not attempt to "handle" it. For example, on some implementations trying to kill a thread causes an exception (that is not a subclass of `std::exception`) to be thrown in that thread so that the thread's stack gets unwinded before stopping the thread. So we shouldn't "catch all exceptions unconditionally" since there may be suprising cases. – adentinger Feb 28 '23 at 21:10
  • @adentinger - it depends. Inside `main()`, like in my example it is a legit thing to do, because you might want to log and exit, or you might want to abort and dump the core, or whatever, depends on how you operate your software. – bobah Mar 26 '23 at 12:35
  • @bobah Yes, you're right; that pretty much what I meant too! We should only handle errors when we know what to do with them. We should just recognize that `catch(...)` may catch stuff that we don't want to catch. IMO, the bottom line is: in the majority of cases, we should re-throw or terminate the program inside `catch(...)` after e.g. logging. But yes, in a few cases, if we really, really know what to do because we've read the compiler's documentation and the standard and we know what's right for our application, then we should do that of course! – adentinger Mar 26 '23 at 18:52
75
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.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
60

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.

Clearer
  • 2,166
  • 23
  • 38
39

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

sg7
  • 6,108
  • 2
  • 32
  • 40
Mellester
  • 922
  • 7
  • 9
  • 7
    its better to using RAII for memory management that automatically handle this exception situations. – hich9n Mar 29 '14 at 07:14
  • 1
    @paykoob How does that handle cases where you manged to create a new foo but it failed on a bar. Or when the constructor of bar trys to open a file but fails and therefore throws. then you might end up with a dangeling foo – Mellester Dec 08 '14 at 18:39
  • 2
    @MelleSterk Wouldn't the stack still get cleaned up in that case, which would run `Foo`'s destructor? I thought that was the whole point of RAII. However, if you need a pointer to a `Foo` rather than just creating the `Foo` on the stack, then you'd need to wrap the pointer in something else that is declared on the stack. – reirab Apr 04 '15 at 08:05
  • yes auto foo = std::make_unique(); auto bar = std::make_unique(); // is exception safe and will not leak, no catch(...) required – paulm Apr 13 '15 at 06:54
  • 2
    Me from the future does indeed agree me from the past did not understand RAII at that time – Mellester Feb 15 '19 at 21:23
23

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.

Trevor Hickey
  • 36,288
  • 32
  • 162
  • 271
Infintyyy
  • 929
  • 1
  • 11
  • 23
19

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.

John D. Cook
  • 29,517
  • 10
  • 67
  • 94
  • 2
    I just caught some usages of these and peppered in some logging at that stage. Doing nothing with an exception is definitely asking for trouble. – jxramos May 09 '16 at 21:24
  • Why trouble? Also can we log some kind of e.what() on exceptions caught within (...)? – Maf Mar 16 '23 at 12:20
16

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.

Paul Sonier
  • 38,903
  • 3
  • 77
  • 117
  • 2
    Of course, you should never catch Error objects -- if you were supposed to catch them they would be Exceptions. Error objects are completely fatal things, such as running out of heap space etc. – SCdF Nov 25 '08 at 02:03
  • 1
    Neither runtime exceptions which are most of the times GoodProgrammerExpected exceptions!!! – OscarRyz Nov 25 '08 at 21:21
  • 3
    We had a really serious bug caused by catching an OutOfMemoryError due to a catch(Throwable) block instead of letting it kill things... – Hakanai Jun 28 '12 at 02:36
  • 1
    Of course `catch(Exception)` may not catch all exceptions in Java, you are getting it mixed up with C#... Java = `catch(Thowable)`, C# = `catch(Exception)`. Don't get them confused. – Chef Pharaoh Jan 09 '13 at 14:48
  • 2
    @OscarRyz That sounds like the `CoderMalfunctionError` (which is actually a real Java `Error` subclass... though it doesn't mean what it sounds like.) – reirab Apr 04 '15 at 08:01
  • Maybe the code catching `Throwable` or `Error` or one of the derived classes from `Error` calls it an exception. But although it is a fault condition, Java explicitly distinguishes errors and exceptions. Your answer here simply muddles it back together again. If you throw an error in your code then you just get the error / stacktrace back (unless the entire system is buggered up, of course). – Maarten Bodewes Sep 07 '16 at 15:08
  • 1
    This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post. – Donald Duck Sep 07 '18 at 11:10
12

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)

Aftershock
  • 5,205
  • 4
  • 51
  • 64
10

Be aware

try{
// ...
} catch (...) {
// ...
}

catches only language-level exceptions, other low-level exceptions/errors like Access Violation and Segmentation Fault wont be caught.

muaz
  • 550
  • 9
  • 15
  • 2
    Things like Segmentation Fault are not actually exceptions, they are signals; thus, you cannot catch them like typical exceptions. However, there are some workarounds like [this](https://stackoverflow.com/questions/2350489/how-to-catch-segmentation-fault-in-linux). – MAChitgarha Mar 26 '20 at 15:01
  • what is difference between `catch(...)` vs `catch(std::exception)`? – Mayur Nov 12 '20 at 11:00
  • 1
    @Mayur `catch(...)` catches **all** language level thrown exceptions, on the other hand `catch(std::exception)` catches only exceptions of type `std::exception`, for example if you call `throw 5` only `catch(...)` will catch that. – muaz Nov 12 '20 at 21:11
  • Is there any additional cost on catching all exceptions? – Maf Mar 16 '23 at 12:16
  • 1
    @Maf exception handling does not come for free, so it has a cost compared to no exception or error handling, but if you meant: catching all vs catching specific exception, i believe it is cheaper since no exception type check is there, but of course just an opinion with no proof. – muaz Mar 17 '23 at 14:14
  • @muaz I would say if you have less processing cost, you have much more memory cost in this case to carry out all the exceptions. – Maf Mar 17 '23 at 14:43
6

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

Shog9
  • 156,901
  • 35
  • 231
  • 235
  • 15
    I disagree, there's plenty of cases in real time applications where I'd rather catch an unknown exception, write *anything* to a log/ pursue some generic error course of action, rather than letting the application crash. – f0ster Sep 13 '11 at 16:57
  • 3
    I rather suspect you're thinking of cases where you *can* pursue some generic error course of action, conveniently ignoring those where the stack is trashed or memory is exhausted and generic error-handling isn't going to succeed either. Nothing wrong with catching errors that you *can* recover from, but IMHO a catch-all should really exist only as isolated (separate stack, pre-allocated memory), carefully-written logic called just prior to program termination; if you don't know what the problem is, you can't be confident that it can be recovered from. – Shog9 Sep 13 '11 at 17:22
  • 1
    I.e. install a signal handler which unwinds some log you build during runtime to figure out where the program crashed and, hopefully, why. – Clearer May 26 '14 at 14:19
  • For example, I have a suite of unit tests. If one test dies, I want to log it, and then *keep testing*. – Edward Falk Aug 21 '21 at 05:53
  • @Shog9 I totally disagree. You know that on a crash code is broken, but not where. If the code is in production, you want to log it so you can know what happened . User informations are normally bullshit: they don't know what they have done, everything is random. if you don't know what the problem is - it is almost impossible to find it. – Offler Nov 17 '21 at 08:15
  • Which is why you really just want to log whatever information is available and terminate, @offler. A core dump isnt much fun, but is certainly less prone to misremembering than the user. – Shog9 Nov 18 '21 at 16:54
4
  1. 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.

  2. 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?

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

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

orcmid
  • 2,618
  • 19
  • 20
3

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

mihi
  • 6,507
  • 1
  • 38
  • 48
2

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.

Fedor
  • 17,146
  • 13
  • 40
  • 131
1

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.

Paul Floyd
  • 5,530
  • 5
  • 29
  • 43
Jan
  • 19
  • 1