C++ 在catch块中调用GetLastError会产生不正确的值
今天探索一些遗留代码很有趣。遇到了这个小数字:C++ 在catch块中调用GetLastError会产生不正确的值,c++,exception,getlasterror,C++,Exception,Getlasterror,今天探索一些遗留代码很有趣。遇到了这个小数字: function Func1() { DWORD dwError; try { dwError = 1; throw "Hey!"; } catch (LPCTSTR szError) { Log("Log1: %d", dwError); SetLastError(dwError); throw szError; } } function Func2() { try { Func1(
function Func1()
{
DWORD dwError;
try
{
dwError = 1;
throw "Hey!";
} catch (LPCTSTR szError)
{
Log("Log1: %d", dwError);
SetLastError(dwError);
throw szError;
}
}
function Func2()
{
try {
Func1();
}
catch (LPCTSTR szError)
{
DWORD dwLastError = GetLastError();
Log("Log2: %d", dwLastError); ///OMG is 0!
}
}
GetLastError()
返回0!为什么呢?这些函数实际上比这个复杂一点。它们确实包括堆栈上的一些内容(DWORDs、CString、BYTE[])。我应该找什么
日志如下所示:
日志1:1
Log2:0MSVC编译器和运行时中的C++异常是在本机Windows SEH之上构建的。堆栈展开实际上是由Windows执行的。使用Windows api函数将影响为GetLastError()存储的值。有关中SEH连接的更多详细信息。如果调用
SetLastError
将当前线程的“last error”值设置为零,很明显,如果没有调用其他修改它的函数,GetLastError
将返回零。。。您的问题到底是什么?SetLastError应该将最后一个错误设置为1而不是0通常不抛出接收到的异常,只需使用throw呃,对不起,不知什么原因我错过了1:S您确定在抛出
和捕获
之间没有调用Windows函数吗?可能是堆栈上创建的对象的析构函数。。。否则,可能是管理异常的CRT代码使用了一些设置上次错误状态的Windows函数。无论如何,如果您想传递GetLastError
的状态,最好在抛出异常时将其拾取并封装到抛出的异常中。@Adam:我建议的throw
不会解决任何问题。它只是防止重新创建“隐藏”异常对象。对于像您这样的指针,它没有真正的区别。如果我要编译项目/EHs,会不会发生这种情况?会的,抛出异常和展开堆栈是由winapi函数在后台完成的,而不管编译选项如何。谢谢Hans。不过,我确实发现了一些有趣的东西,我应该把它们包括在问题中/clr已打开。如果我关闭/clr,GetLastError()的行为将正确。好吧,当您在托管代码中抛出异常时,会运行大量的代码。CLR的异常处理非常复杂。很高兴你提到了这一点,因为我花了很长时间才找到关于RaiseException和RtlUnwindEx()如何影响GetLastError:)的文档,我完全应该在原始帖子中包含这一点…嗯…:P再次感谢。