What's better to use, a __try/__except block or a try / catch block?

27,864

Solution 1

You should use a try/catch block.

As others have already answered, __try / __except is for catching SEH (windows generated errors) not for catching general exceptions.

Most importantly, __try and __catch may not run C++ destructors or correctly unwind the stack when an exception is thrown.

Except in rare cases, you should never try to catch SEH exceptions.

EDIT: Well, I was positive on this (it's what I've always been told), but @Hans says that apparently there is a compiler switch you can use to change this. I think the docs on /EHa are misleading, or at least incomplete, on what happens here. If someone finds definitive docs which prove this wrong, I'll happily remove this answer.

Even if it turns out this is false, you should still use try and catch simply because they are standard, while __try and __except are not.

Solution 2

They are two very different things. try/catch are the familiar C++ keywords you know. __try/__except is used to catch SEH exceptions. Exceptions raised by Windows itself, like DivisionByZero or AccessViolation. It is well described in the MSDN Library article for it.

You can also use it to catch C++ exception because it leverages the Windows SEH feature. You however can't get the thrown exception object out of it so there will be zero context if you actually want the handle the exception. Which is madness. The number one approach is to not ever catch SEH exceptions, they are always gross. If you do need to marry the two then use _set_se_translator() to convert the SEH exception to a C++ exception.

Solution 3

__try/__except is designed for calling Win32 C code which doesn't support exceptions but does use a structured error code / handling mechanism. __try/__except will translate C errors into an exception block similar to C++ try/catch.

For more information, see this MSDN article.

Solution 4

Standard C++ uses try/catch blocks, so I would recommend using them, if you need the "standard" exception mechanism, based on standard C++ library.

However, if you plan to use Structured Exception Handling provided through Windows SDK (see here), then use __try/__except.

Solution 5

Once you've thrown something, you no longer have much choice about how to catch it. If you throw C++ exceptions (i.e., with throw), then use try/catch. If you throw Windows exceptions (i.e., with RaiseException), then use __try/__except. Trying to mix them will just be adding unnecessary hassle to your life.

Share:
27,864
Zain Rizvi
Author by

Zain Rizvi

"I'm gonna need more bug spray" Software Engineer, I've worked at Google and Microsoft, in of the AI Platform Notebooks and Azure Web App teams respectively My blog, where I post interesting things I learn about tech, psychology, business, and self-improvement: http://zainrizvi.io

Updated on September 04, 2020

Comments

  • Zain Rizvi
    Zain Rizvi over 3 years

    I'm wondering which is the better way to catch exceptions that I throw: is it a __try / __except block or a try / catch block?

    I'm writing in C++ and the program will only be used on Windows, so portability is not an issue.

    Thanks!

  • Billy ONeal
    Billy ONeal over 13 years
    -1: The STL has absolutely nothing to do with exception handling.
  • Cătălin Pitiș
    Cătălin Pitiș over 13 years
    The STL has absolutely something to do with exception handling: std::exception, which is the recommended base class for exceptions, even if it is not mandatory.
  • Billy ONeal
    Billy ONeal over 13 years
    std::exception is not an STL class.
  • Cătălin Pitiș
    Cătălin Pitiș over 13 years
    Sorry. Standard C++ Library is better phrased?
  • Billy ONeal
    Billy ONeal over 13 years
    @Cătălin Pitiș: Yes, that would be better, but still wouldn't be quite pedantic :) (I would remove my downvote after an edit to that effect)
  • David Thornley
    David Thornley over 13 years
    So it doesn't unwind the stack? That means that it's probably a really bad idea to use __try/__except as anything other than a crash reporting system, whereas it's common to be able to recover from an exception in a try/catch block.
  • Billy ONeal
    Billy ONeal over 13 years
    @David: That is correct. __try and __except are strictly a C based API/ABI.
  • Donal Fellows
    Donal Fellows over 13 years
    The only good uses for it I've seen have been dealing with what amounted to bugs in Windows itself (such as what used to happen when you tried to copy a device). Arguably they're always indicative of somewhere where Windows should have caught the exception for you and translated it into an error. (The way they work is horrific too, and very very x86-specific…)
  • Billy ONeal
    Billy ONeal over 13 years
    But you should never thrown windows exceptions because they do not unwind the stack.
  • user1703401
    user1703401 over 13 years
    That's not accurate. Compiling with /EHa guarantees C++ destructor calls during stack unwinding.
  • Billy ONeal
    Billy ONeal over 13 years
    @Hans: Can you find documentation to that effect? My understanding of /EHa is merely that it allows C++ exception handling constructs (when you use try and catch) to catch SEH exceptions, but that the C++ stack is still not correctly unwound when __try and __except are used.
  • user1703401
    user1703401 over 13 years
    The /EH documentation is all there is. Yes, it isn't great. /EHa suppresses a compiler optimization that omits exception cleanup handlers when the compiler detects that none of the emitted code can throw a C++ exception. You can see them when you look at the machine code.
  • Alexandru
    Alexandru about 10 years
    I don't think I agree with this answer...this seems to work just fine for me in terms of catching C++ exceptions: __try { for (int *i = 0; *i < 100; i++) { *i = 10000; } } __except (FatalExceptionFilter(GetExceptionInformation(), GetExceptionCode())) { } Am I missing something here?
  • Billy ONeal
    Billy ONeal about 10 years
    @Alex: __except can catch C++ exceptions; but my understanding is that it is not guaranteed to provide C++ stack unwind semantics while doing so. Except, as Hans claims, under /EHa. (Please please please don't use /EHa)
  • Alexandru
    Alexandru about 10 years
    There's times where you don't want it to unwind the stack, specifically because you wanna catch the stack trace exactly where a problem happens on an application crash :)
  • Billy ONeal
    Billy ONeal about 10 years
    @Alexandru: IF you want a stack trace you should let the application crash, and grab the minidump. The app generating its own stack trace requires symbols to be available, and those should generally speaking not be shipped with the app.
  • Alexandru
    Alexandru about 10 years
    @BillyONeal Its true, shipping PDB's would make it easier to reverse-engineer your code. In cases where your solutions are hosted, it should be alright. If someone's going to reverse engineer your code, they'd probably be able to do it regardless...it just won't be as close of a match to the original. :)
  • Billy ONeal
    Billy ONeal about 10 years
    @Alexandru: No, I'm not saying due to reverse engineering. I'm saying because you're burning 3x the drive space you need to burn for your app by forcing all your customers to install .pdbs. Having the app try to generate its own stack trace is like having a train where a car comes off the tracks, and while the train is still running at 80 miles an hour trying to figure out the root cause. Don't do that. Stop the train (crash) and figure out the problem afterward.
  • Alexandru
    Alexandru about 10 years
    @BillyONeal That's a good point but space is cheap nowadays, so I'm not overly concerned about that. This is getting opinionated; I understand your point though.
  • chacham15
    chacham15 almost 4 years
    @BillyONeal apparently its the only way of setting a thread name pre-windows10 though: docs.microsoft.com/en-us/visualstudio/debugger/…
  • Rob Kennedy
    Rob Kennedy almost 4 years
    Stack unwinding is irrelevant in that case, @chacham, because you're only throwing to get the debugger's attention, not to change the program's flow. You immediately catch and discard the exception. The point remains, though, that you have no real choice about how you catch that exception. You throw it with RaiseException, so you must catch it with __except.
  • chacham15
    chacham15 almost 4 years
    Sure, but "But you should never thrown windows exceptions" isnt entirely accurate.