前段时间写了一篇关于C++异常捕获及异常处理的文章:
c++异常捕获及异常处理try-throw-catch
严格的来说,那不算是一篇完整的文章,更多的是提出我的疑惑。顺便总结了一下网友关于C++异常捕获及异常处理给出的精炼的示例。
至今,上文提到的疑惑本菜鸟都没有完全解开。
于是,我就选择了用 __try __except 来捕获及处理异常。经过测试,我想捕获的异常用 __try __except 都捕获到了,相当开心。
但是,今天在用 __try __except 的时候蹦出来一个让我既苦恼又兴奋的错误:
error C2712: 无法在要求对象展开的函数中使用__try
本能的打开百度,输入错误提示,一顿查找,并没有找到很好理解的解释。于是我求救 google ,终于找到了我能很容易理解的解释。(哎,小学语文没学好就是吃亏)
首先,我们来看几个会报C2712错误的示例:
#include <string>
inline std::string foo() { return "abc"; }
inline int foo2() { return 612; }
class MyClass
{
public:
MyClass() { m_val = 0; }
MyClass(int param) { m_val = param; }
~MyClass();
int GetVal() { return m_val; }
private:
int m_val;
};
void TestTryExcept_1()
{
using namespace std;
string str = "666"; // string 是一个类,销毁对象时会调用析构函数,所以会报错
__try
{
// Do anything
}
__except (EXCEPTION_EXECUTE_HANDLE)
{
printf_s("__except\n");
}
// string str; // 无论放在函数里的什么位置都会导致 C2712 错误
}
void TestTryExcept_2()
{
using namespace std;
// foo()返回的是临时的string对象,
// 也就是说,调用foo()时,会生成一个临时的string变量存放返回的数据
// 本质上和TestTryExcept_1()是一样的
foo();
// 和 TestTryExcept_1() 一样使用了 string 类
// string retStr = foo();
__try
{
// Do anything
}
__except (EXCEPTION_EXECUTE_HANDLE)
{
printf_s("__except\n");
}
}
void TestTryExcept_3()
{
// 使用了自己定义的类也会报错,因为销毁对象时同样会调用析构
MyClass ObjA(612);
int ret = ObjA.GetVal();
__try
{
printf_s("__try: %d\n", ret);
}
__except (EXCEPTION_EXECUTE_HANDLE)
{
printf_s("__except\n");
}
}
int _tmain(int argc, _TCHAR* argv[])
{
TestTryExcept_1();
TestTryExcept_2();
TestTryExcept_3();
return 0;
}
上述代码在编译的时候会报C2712错误,原因在代码注释中简单注明了。
其实原因就是:
在使用 __try __except 的函数中任何位置(测试的几个位置都会报错,如有描述错误请告知)创建了类对象就会导致C2712编译错误。
///
msdn上给出的描述和解决方案
Compiler Error C2712
cannot use __try in functions that require object unwinding
When you use /EHsc, a function with structured exception handling cannot have objects that require unwinding (destruction).
Possible solutions:
- Move code that requires SEH to another function
- Rewrite functions that use SEH to avoid the use of local variables and parameters that have destructors. Do not use SEH in constructors or destructors
- Compile without /EHsc
Error C2712 can also occur if you call a method declared by using the __event keyword. Because the event might be used in a multithreaded environment, the compiler generates code that prevents manipulation of the underlying event object, and then encloses the generated code in an SEH try-finally statement. Consequently, error C2712 will occur if you call the event method and pass by value an argument whose type has a destructor. One solution in this case is to pass the argument as a constant reference.
//
我们来将上面三个函数和 main 修改一下:
void TestTryExcept_1()
{
using namespace std;
string str = "666";
printf_s("TestTryExcept_1: %s\n", str.c_str());
}
void TestTryExcept_2()
{
using namespace std;
printf_s("TestTryExcept_2: %s\n", foo());
}
void TestTryExcept_3()
{
MyClass ObjA(612);
int ret = ObjA.GetVal();
printf_s("TestTryExcept_3: %d\n", ret);
}
int _tmain(int argc, _TCHAR* argv[])
{
// 类对象的创建 不能和__try__except在同一个函数中
//using namespace std;
//string str = "main, string object";
//printf_s("%s\n", str);
__try
{
TestTryExcept_1();
TestTryExcept_2();
TestTryExcept_3();
}
__except (EXCEPTION_EXECUTE_HANDLE)
{
printf_s("__except\n");
}
getchar();
return 0;
}
大家可以看到,上述修改后的代码还存在一个问题,就是在 main 中使用了__try __except 后,就无法创建类对象,也就是像 string 这样的类就无法使用了,要不然就会报错。
所以我们再修改一下,把 main 拆成两个函数:
void TestTryExcept_all()
{
__try
{
TestTryExcept_1();
TestTryExcept_2();
TestTryExcept_3();
}
__except (EXCEPTION_EXECUTE_HANDLE)
{
printf_s("__except\n");
}
}
int _tmain(int argc, _TCHAR* argv[])
{
using namespace std;
string str = "main, string object";
printf_s("%s\n", str);
TestTryExcept_all();
getchar();
return 0;
}
这样,所有问题就解决啦。
纯手打,如果有什么问题,欢迎各位大佬指出。
好了,我给大佬递茶去了。。。
声明:上述代码未包含所有需要的头文件,请大家自行脑补。
参考:
Compiler Error C2712
very simple code, and getting error C2712, could not understand why
版权声明
如需转载请注明来源和作者,谢谢!!
本文链接:https://blog.csdn.net/ShiQW5696/article/details/80664749