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:0

MSVC编译器和运行时中的C++异常是在本机Windows SEH之上构建的。堆栈展开实际上是由Windows执行的。使用Windows api函数将影响为GetLastError()存储的值。有关中SEH连接的更多详细信息。

如果调用
SetLastError
将当前线程的“last error”值设置为零,很明显,如果没有调用其他修改它的函数,
GetLastError
将返回零。。。您的问题到底是什么?SetLastError应该将最后一个错误设置为1而不是0通常不抛出接收到的异常,只需使用
throw抛出
捕获
之间没有调用Windows函数吗?可能是堆栈上创建的对象的析构函数。。。否则,可能是管理异常的CRT代码使用了一些设置上次错误状态的Windows函数。无论如何,如果您想传递
GetLastError
的状态,最好在抛出异常时将其拾取并封装到抛出的异常中。@Adam:我建议的
throw
不会解决任何问题。它只是防止重新创建“隐藏”异常对象。对于像您这样的指针,它没有真正的区别。如果我要编译项目/EHs,会不会发生这种情况?会的,抛出异常和展开堆栈是由winapi函数在后台完成的,而不管编译选项如何。谢谢Hans。不过,我确实发现了一些有趣的东西,我应该把它们包括在问题中/clr已打开。如果我关闭/clr,GetLastError()的行为将正确。好吧,当您在托管代码中抛出异常时,会运行大量的代码。CLR的异常处理非常复杂。很高兴你提到了这一点,因为我花了很长时间才找到关于RaiseException和RtlUnwindEx()如何影响GetLastError:)的文档,我完全应该在原始帖子中包含这一点…嗯…:P再次感谢。