为什么创建 std::runtime_error 会重置 WSAGetLastError?

Why does creating a std::runtime_error reset WSAGetLastError?

我正在从 Visual Studio 2013 更新到 Visual Studio 2015,并注意到这种行为差异。

#include <stdexcept>
#include <WinSock2.h>
#include <ws2tcpip.h>

int main()
{
    WORD version = MAKEWORD(2, 2);
    WSADATA wsaData;

    if (WSAStartup(version, &wsaData) != 0)
    {
        throw std::runtime_error("This one is not thrown");
    }

    WSASetLastError(1);

    if (WSAGetLastError() != 1)
    {
        throw std::runtime_error("This one neither");
    }

#if 1
    std::runtime_error test("an error");
#endif

    if (WSAGetLastError() != 1)
    {
        throw std::runtime_error("This is thrown when the above code path is enabled");
    }

    return 0;
}

当我启用 std::runtime_error 代码路径时,WSAGetLastError 标志被重置。禁用它和程序 returns 0 没有任何问题。

documentation 说:

If a function call's return value indicates that error or other relevant data was returned in the error code, WSAGetLastError should be called immediately. This is necessary because some functions may reset the last extended error code to 0 if they succeed, overwriting the extended error code returned by a previously failed function.

显然,创建此错误对象会导致调用重置线程错误代码的函数。

碰巧,WSAGetLastError is an alias for GetLastError 因此创建对象时修改 Win32 线程错误状态也就不足为奇了。

我 运行 在升级到 msvc2015 时遇到了类似的问题...一系列 N 次明显不间断的 WSAGetLastError 调用,最后一次返回的值与第 N-1 次不同。它通过汇编代码逐步查找其中调用 "new" 的构造函数,这有时可能最终需要更多内存,这将重置系统错误代码。课程:如果以后需要,请缓存 WSAGetLastError 的值。