C++, __try and try/catch/finally
C++, __try and try/catch/finally
我对c++的try/catch/finally块有点疑惑。我见过这些带有两个下划线的命令,比如__try。但是MVSC 2010项目也没有下划线。什么时候需要下划线呢?
在Windows上,在操作系统级别支持异常。它们被称为结构化异常处理(SEH),大致相当于Unix信号。为Windows生成代码的编译器通常利用这一点,它们使用SEH基础结构来实现c++异常。
为了与c++标准保持一致,throw和catch关键字只抛出和捕获c++异常。MSVC编译器对应的SEH异常代码为0xe06d7363。最后3个字节是"msc"的ASCII码。
将其与操作系统支持统一还意味着在为SEH异常展开堆栈时将调用c++析构函数。执行展开的代码位于Windows内部,并以与任何SEH完全相同的方式处理throw引发的SEH。然而,Microsoft编译器有一个优化,它试图避免生成确保在所有情况下都调用析构函数所需的代码。如果它能证明在控制对象生命周期的作用域块内没有throw语句,那么它就跳过注册码。这与异步SEH异常不兼容,如果您打算捕获SEH异常,您应该使用/EHa compile选项来抑制此优化。
有很多SEH异常类型。操作系统可以生成的SDK在ntstatus.h SDK头文件中列出。此外,您可以与使用SEH实现自己的异常处理的代码进行互操作,它们将使用自己的异常代码。与。net一样,托管异常使用0xe0434f4d ("com")异常代码。
要在c++程序中捕获SEH异常,必须使用非标准的__try关键字。__except关键字类似于c++的catch关键字。它有更多的功能,您可以指定一个异常筛选器表达式来确定是否应该捕获活动异常。一切皆有可能,但通常只查看传递的异常信息,以确定是否有兴趣处理它。__finally关键字允许你编写在异常处理后运行的代码。在c++中没有对应的,但在其他语言中并不少见。
正如评论中指出的那样,所有这些都是相当糟糕的文档。事实就是这样。下面是一个示例程序,您可以试用一下。它演示了SEH异常如何仍然允许调用c++析构函数(如果使用/EHa进行编译),以及如何在SEH之上实现c++异常。需要MSVC编译器,使用Ctrl+F5运行以避免调试器的帮助:
#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
__try
/__except
用于捕获SEH (windows生成的错误)而不是用于捕获一般异常。
try
/catch
是c++标准为处理一般c++异常所指定的。
对于你写的标准c++代码,你应该总是使用try
/catch
而不是__try
/__except
此外,finally
不是c++标准指定的构造,它为您工作,因为它是一个微软编译器扩展。
__try/__except
是Microsoft专用的。如果您希望您的代码可以在其他编译器(例如g++)(或)在其他操作系统中编译,请避免使用它们,并坚持使用标准的try/catch
语句
- C++ Python "try: except:"版本
- 编译器是否必须始终删除 try-catch 块(如果它被证明是非抛出的)
- 有没有更好的方法来处理异常? try-catch块真的很丑
- 当无法进行RAII时,如何在C++中"try/finally"?
- 我可以使用 try catch 语句来捕获任何错误而不是具体错误吗?
- 在大型应用程序的main上使用try-catch
- RapidXML 节点在 try catch 块中具有正确的值,但它在块外为 nullptr
- 提取 try-catch 时出现运行时错误
- C++:在"try"外部创建的类型会导致错误,但在内部不会
- std::unique_ptr 在 try-catch 块中未捕获取消引用异常
- 何时删除 try-catch 块中的指针
- 是否有理由大多数/所有 try-catch 示例只对 throw 语句使用 void 子函数
- 循环try..catch ..确保输入有效或使用控制语句
- 构造函数中的异常:init() 方法、指针、大型 try/catch 或
- 尝试在 Kdevelop中调试时如何修复"WebConnect: Starting server failed. Try to remove stale socket."?
- C++ C2509 在讲师的定义中使用 try: - catch
- 为什么未达到的 try-catch 块会增加运行时时间
- 在 C++ 中使用 try-catch 进行删除 [] 或删除操作是否必要
- 如何确保(像try-finally一样)销毁heap分配的对象
- C++, __try and try/catch/finally