天天看点

“error C2712: 无法在要求对象展开的函数中使用__try”解决方案Compiler Error C2712

前段时间写了一篇关于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

继续阅读