C ++,__try和try / catch / finally [英] C++, __try and try/catch/finally

查看:263
本文介绍了C ++,__try和try / catch / finally的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道一点关于C + + try / catch / finally块。我看到这些命令有两个下划线,如__try。但MVSC 2010项目也没有下划线运行。

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?

推荐答案

在Windows上,操作系统级别支持异常。调用结构化异常处理(SEH),它们大致相当于Unix信号。为Windows生成代码的编译器通常会利用这一点,他们使用SEH基础结构来实现C ++异常。

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.

为了符合C ++标准, / em>和 catch 关键字只能抛出和捕获C ++异常。 MSVC编译器的相应SEH异常代码为0xe06d7343。最后3个字节是msc的ASCII代码。

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 0xe06d7343. The last 3 bytes are the ASCII code for "msc".

使用操作系统支持来统一它也意味着C ++析构函数将在堆栈展开期间被调用,用于SEH异常。展开的代码在Windows内部,并且以与任何SEH完全相同的方式处理由 throw 引发的SEH。然而,Microsoft编译器有一个优化,试图避免生成所需的代码,确保在所有情况下调用析构函数。如果它可以证明在控制对象的生命周期的范围块中没有throw语句,那么它会跳过注册代码。这与异步SEH异常不兼容,如果您打算捕获SEH异常,应该使用/ EHa编译选项抑制此优化。

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.

有很多SEH异常类型。可由操作系统生成的文件列在ntstatus.h SDK头文件中。此外,您可以与使用SEH来实现自己的异常处理的代码交互,它们将使用自己的异常代码。像.NET一样,托管异常使用0xe0434f4d(com)异常代码。

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.

要在C ++程序中捕获SEH异常,必须使用非标准的__try关键字。 __except关键字类似于C ++ catch 关键字。它具有更多功能,您可以指定一个异常过滤器表达式来确定是否应捕获活动异常。任何事情都是可能的,但你通常只看传递的异常信息,看看你是否有兴趣处理它。 __finally关键字允许您编写在处理异常后运行的代码。在C ++中没有等效项,但在其他语言中不常见。

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.

所有这些都是在评论中指出的。证明是在布丁。这里是一个示例程序,你可以玩。它演示了SEH异常如何允许调用C ++析构函数,前提是使用/ EHa编译并且如何在SEH上实现C ++异常。需要MSVC编译器,请使用Ctrl + F5运行以避免调试器有帮助:

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;
}

输出:

Filtering c0000005
destructed
caught
Filtering e06d7363
destructed
caught

这篇关于C ++,__try和try / catch / finally的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆