Почему создание std::runtime_error сбрасывает 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 сбрасываются. Отключите его, и программа без проблем вернет 0.


person bofjas    schedule 07.03.2016    source источник
comment
Где ваш звонок WSAStartup? Ознакомьтесь с документацией: msdn. microsoft.com/en-us/library/windows/desktop/   -  person PaulMcKenzie    schedule 07.03.2016
comment
Я удалил весь код, который не был необходим для воспроизведения проблемы, чтобы сделать исходный код более удобным для переполнения стека. Первоначально у меня был WSAStartup в начале, и поведение было идентичным.   -  person bofjas    schedule 07.03.2016
comment
Исправлено, чтобы не отвлекать внимание от фактического вопроса   -  person bofjas    schedule 07.03.2016


Ответы (2)


В документации говорится:

Если возвращаемое значение вызова функции указывает на то, что ошибка или другие соответствующие данные были возвращены в коде ошибки, следует немедленно вызвать WSAGetLastError. Это необходимо, поскольку некоторые функции могут сбрасывать последний расширенный код ошибки на 0 в случае успеха, перезаписывая расширенный код ошибки, возвращенный ранее неудачной функцией.

Очевидно, что создание этого объекта ошибки приводит к вызову функции, которая сбрасывает код ошибки потока.

Как оказалось, WSAGetLastError является псевдонимом для GetLastError, так что вряд ли удивительно, что статус ошибки потока Win32 изменяется при создании объекта.

person David Heffernan    schedule 07.03.2016
comment
Я действительно видел этот абзац, но предположил, что только другие методы WSA сбрасывают флаг. Немного странно, что простое создание исключения изменит глобальный флаг ошибки, и, поскольку он менялся между версиями VS, мне было интересно, была ли это ошибка. Но я предполагаю, что это соответствует поведению в абзаце. Спасибо. - person bofjas; 07.03.2016
comment
как узнать, что делает или не делает std::runtime_error()? Потенциально он регистрируется в каком-то файле и, таким образом, вызывает WriteFile(). И почему вы хотите предположить что-то вроде этого? - person ; 24.04.2016
comment
@Excess, кому это адресовано? - person David Heffernan; 24.04.2016

Я столкнулся с чем-то похожим при обновлении до msvc2015... серия N явно непрерывных вызовов WSAGetLastError, причем последний из них возвращает значение, отличное от первого N-1. Потребовалось пошаговое выполнение ассемблерного кода, чтобы найти конструктор с вызовом «нового» в нем, что, вероятно, иногда требовало больше памяти, что приводило к сбросу кода системной ошибки. Урок: кэшируйте значение из WSAGetLastError, если оно понадобится вам позже.

person blindchimp    schedule 16.06.2016