Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++, __try and try/catch/finally

I'm wondering a bit about C++ try/catch/finally blocks. I've seen these commands with two underscores like __try. But MVSC 2010 projects also run without the underscores. So when do you need these underscores?

like image 554
martin Avatar asked Aug 13 '11 09:08

martin


People also ask

Does C have try and catch?

Try-Catch mechanisms are common in many programming languages such as Python, C++, and JavaScript.

What is finally in try catch?

The try statement defines the code block to run (to try). The catch statement defines a code block to handle any error. The finally statement defines a code block to run regardless of the result.

Is there try and except in C?

The try-except statement is a Microsoft extension to the C language that enables applications to gain control of a program when events that normally terminate execution occur. Such events are called exceptions, and the mechanism that deals with exceptions is called structured exception handling.

What is the use of try catch and finally blocks in C#?

catch − A program catches an exception with an exception handler at the place in a program where you want to handle the problem. The catch keyword indicates the catching of an exception. finally − The finally block is used to execute a given set of statements, whether an exception is thrown or not thrown.


2 Answers

On Windows, exceptions are supported at the operating system level. Called Structured Exception Handling (SEH), they are the rough equivalent to Unix signals. Compilers that generate code for Windows typically take advantage of this, they use the SEH infrastructure to implement C++ exceptions.

In keeping with the C++ standard, the throw and catch keywords only ever throw and catch C++ exceptions. The corresponding SEH exception code for the MSVC compiler is 0xe06d7363. The last 3 bytes are the ASCII code for "msc".

Unifying it with the operating system support also means that C++ destructors will be called during stack unwinding for an SEH exception. The code that does the unwinding is inside Windows and treats the SEH raised by a throw the exact same way as any SEH. However, the Microsoft compiler has an optimization that tries to avoid generating the code required that ensures that destructors are called in all cases. If it can prove that there's no throw statement inside the scope block that controls the object's lifetime then it skips the registration code. This is not compatible with asynchronous SEH exceptions, you should use the /EHa compile option to suppress this optimization if you intend to catch SEH exceptions.

There are a lot of SEH exception types. The ones that can be generated by the operating system are listed in the ntstatus.h SDK header file. In addition, you might interop with code that uses SEH to implement their own exception handling, they will use their own exception code. Like .NET, managed exceptions use the 0xe0434f4d ("com") exception code.

To catch SEH exceptions in a C++ program, you must use the non-standard __try keyword. The __except keyword is analogous to the C++ catch keyword. It has more capabilities, you specify an exception filter expression that determines whether or not an active exception should be caught. Anything is possible, but you typically only look at the passed exception information to see if you're interested in handling it. The __finally keyword lets you write code that runs after the exception is handled. No equivalent for that in C++ but not uncommon in other languages.

All of this is fairly poorly documented as pointed out in the comments. The proof is in the pudding. Here's an example program that you can play with. It demonstrates how SEH exceptions still allows for C++ destructors to be called, provided you compile with /EHa and how C++ exceptions are implemented on top of SEH. MSVC compiler required, run with Ctrl+F5 to avoid the debugger being helpful:

#include "stdafx.h" #include <windows.h> #include <iostream>  // NOTE: the value of the C/C++, Code Generation, Enable C++ Exceptions setting in important // Try it both with /EHsc (the default) and /EHa to see the difference  class Example {   public:     ~Example() { std::cout << "destructed" << std::endl; } };  int filterException(int code, PEXCEPTION_POINTERS ex) {     std::cout << "Filtering " << std::hex << code << std::endl;     return EXCEPTION_EXECUTE_HANDLER; }  void testProcessorFault() {     Example e;     int* p = 0;     *p = 42; }  void testCppException() {     Example e;     throw 42; }  int main() {     __try {         testProcessorFault();     }     __except(filterException(GetExceptionCode(), GetExceptionInformation())) {         std::cout << "caught" << std::endl;     }     __try {         testCppException();     }     __except(filterException(GetExceptionCode(), GetExceptionInformation())) {         std::cout << "caught" << std::endl;     }     return 0; } 

Output:

Filtering c0000005 destructed caught Filtering e06d7363 destructed caught 
like image 100
Hans Passant Avatar answered Oct 19 '22 21:10

Hans Passant


__try / __except is for catching SEH (windows generated errors) not for catching general exceptions.

try / catch is what the C++ standard specifies for handling general C++ exceptions.

For the standard C++ code you write you should always use try/ catch and not __try / __except

Also, finally is not C++ Standard specified construct, It works for you because it is a Microsoft compiler extension.

like image 33
5 revs, 2 users 71% Avatar answered Oct 19 '22 21:10

5 revs, 2 users 71%