Переполнение стека при попытке вернуть уникальный указатель с VS2015 и addrinfoW - PullRequest
0 голосов
/ 12 апреля 2019

Я сделал некоторый код для извлечения адресов из DNS, и у меня происходит сбой.Вот мой код:

#include <ws2tcpip.h>
#include <winSock2.h>

// Need to link with Ws2_32.lib
#pragma comment(lib, "ws2_32.lib")
#include <memory>
#include <random>

bool resolveHost(const wchar_t* hostname, uint16_t port);

int main(int argc, char *argv[]) {
    WSADATA wsaData;

    WSAStartup(
      MAKEWORD(2,2),
      &wsaData
    );
    auto l = resolveHost(L"your own DNS here", 80);
}

std::unique_ptr<addrinfoW, decltype (&FreeAddrInfoW)> getAddrInfo(const wchar_t* hostname, quint16 defaultPort)
{
    addrinfoW* result;
    // zero initialization
    addrinfoW hints = {};
    hints.ai_socktype = SOCK_STREAM;
    wchar_t port[9];
    int error = swprintf_s(port, sizeof (port), L"%hu", defaultPort);
    if(error == -1)
    {
        printf("Invalid call to swprintf_s");
        return std::unique_ptr<addrinfoW, decltype (&FreeAddrInfoW)>{nullptr, &FreeAddrInfoW};
    }
    /* resolve the domain name into a list of addresses */
    error = GetAddrInfoW(hostname, port, &hints, &result);
    if (error != 0)
    {
        wprintf(gai_strerror(error));
        return std::unique_ptr<addrinfoW, decltype (&FreeAddrInfoW)>{nullptr, &FreeAddrInfoW};
    }
// here, when I return, I have a stack overflow
    return std::move(std::unique_ptr<addrinfoW, decltype (&FreeAddrInfoW)>{result, &FreeAddrInfoW});
}

bool resolveHost(const wchar_t hostname, uint16_t port)
{
    auto guard {getAddrInfo(hostname, port)};
    return true;
}

Когда возвращается getAddrInfo, у меня переполнение стека с VS 2015 (у меня нет другой версии), и я не понимаю, почему.Кто-нибудь может мне помочь?

1 Ответ

2 голосов
/ 12 апреля 2019

Вы передаете размер массива в байтах вместо количества элементов массива в swprintf_s, что может привести к повреждению стека.В режиме отладки он заполняет оставшуюся часть буфера после завершения нуля с маркер мусора 0xFE .Обратите внимание, что существует соответствующая перегрузка для swprintf_s размера вывода массива в стиле c, поэтому нет необходимости передавать его явно.

Также не должно быть std::move( в последнем операторе возврата.

...