Winsock代码在freeaddrinfo中崩溃

时间:2014-06-30 13:55:25

标签: c++ sockets networking

我在使用freeaddrinfo(...)和Visual Studio 2012 x64的网络代码时出现问题。代码看起来像这样:

struct addrinfo hints = {0};
hints.ai_family = AF_INET;      // only use IPv4
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags =  AI_ADDRCONFIG;

struct addrinfo *res = nullptr;
int status = getaddrinfo(_rIP.c_str(), std::to_string(_port).c_str(), &hints, &res);
if (status == 0)
{
    addDestAddress(res->ai_addr);
}

freeaddrinfo(res);

getaddrinfo / freeaddrinfo在整个代码中的一些地方使用,我得到了一致 在发布模式下崩溃。 addDestAddress的代码如下:

void addDestAddress(const sockaddr *_pAddr)
{
    m_vecDestAddrs.push_back(*(sockaddr_storage*)_pAddr);
}

这是freeaddrinfo的正确用法吗?如果我删除freeaddrinfo调用,除了可能的内存泄漏之外,一切都能正常工作。

修改 这段代码现在完美无缺。据Remy Lebeau的回答编辑。

struct addrinfo hints = {0};
hints.ai_family = AF_INET;  // only use IPv4
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags =  AI_ADDRCONFIG;

struct addrinfo *res = nullptr;
int status = getaddrinfo(_rIP.c_str(), std::to_string(_port).c_str(), &hints, &res);
if (status == 0)
{
    if (res->ai_family == AF_INET)
    {
        addDestAddress((sockaddr_in*)res->ai_addr);
    }

    freeaddrinfo(res);
}

addDestAddress的代码如下:

void addDestAddress(const sockaddr_in *_pAddr)
{
    sockaddr_storage ssaddr = {0};
    memcpy(&ssaddr, _pAddr, sizeof(sockaddr_in));
    m_vecDestAddrs.push_back(ssaddr);
}

这仅用于IPv4 UDP工作,不需要IPv6支持。

2 个答案:

答案 0 :(得分:1)

来自documentation,强调:

  

通过成功调用此函数分配的内存必须在随后调用freeaddrinfo时释放。

你没有听从这个指示。您无条件致电freeaddrinfo。只有在freeaddrinfo的来电成功时,您才能致电getaddrinfo

答案 1 :(得分:1)

你犯了两个错误:

  1. 即使freeaddrinfo()失败,您也在呼叫getaddrinfo()。不要那样做。

  2. 您假设res->ai_addrsockaddr_storage*,但事实并非如此。这是sockaddr_in*,因为hints.ai_familyAF_INET(如果您使用AF_INET6,则会sockaddr_in6AF_UNSPEC可能是sockaddr_in任意一个)。 sockaddr_storage小于ai_addr,因此您在将struct addrinfo hints = {0}; hints.ai_family = AF_INET; // only use IPv4 hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = AI_ADDRCONFIG; struct addrinfo *res = nullptr; int status = getaddrinfo(_rIP.c_str(), std::to_string(_port).c_str(), &hints, &res); if (status == 0) { addDestAddress((sockaddr_in*) res->ai_addr); freeaddrinfo(res); } void addDestAddress(const sockaddr_in *_pAddr) { sockaddr_storage ssaddr = {0}; memcpy(&ssaddr, _pAddr, sizeof(sockaddr_in)); m_vecDestAddrs.push_back(ssaddr); } 数据复制到矢量时错误地访问了内存。

  3. 请改为尝试:

    struct addrinfo hints = {0};
    hints.ai_family = AF_INET;      // only use IPv4
    hints.ai_socktype = SOCK_DGRAM;
    hints.ai_flags =  AI_ADDRCONFIG;
    
    struct addrinfo *res = nullptr;
    int status = getaddrinfo(_rIP.c_str(), std::to_string(_port).c_str(), &hints, &res);
    if (status == 0)
    {
        addDestAddress(res->ai_addr, res->ai_addrlen);
        freeaddrinfo(res);
    }
    
    void addDestAddress(const sockaddr *_pAddr, int addrlen)
    {
        switch (addrlen)
        {
            case sizeof(sockaddr_in):
            case sizeof(sockaddr_in6):
            {
                sockaddr_storage ssaddr = {0};
                memcpy(&ssaddr, _pAddr, addrlen);
                m_vecDestAddrs.push_back(ssaddr);
                break;
            }
        }
    }
    

    或者这个:

    {{1}}