天天看點

“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

繼續閱讀