首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Winsock代码在freeaddrinfo中崩溃

Winsock代码在freeaddrinfo中崩溃
EN

Stack Overflow用户
提问于 2014-06-30 13:55:24
回答 2查看 879关注 0票数 0

我在使用freeaddrinfo(.)的一些网络代码上遇到了麻烦。使用2012 x64。代码如下所示:

代码语言:javascript
运行
复制
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的代码如下:

代码语言:javascript
运行
复制
void addDestAddress(const sockaddr *_pAddr)
{
    m_vecDestAddrs.push_back(*(sockaddr_storage*)_pAddr);
}

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

编辑--这段代码现在工作得很完美。根据雷米·莱博的答案编辑。

代码语言:javascript
运行
复制
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的代码如下:

代码语言:javascript
运行
复制
void addDestAddress(const sockaddr_in *_pAddr)
{
    sockaddr_storage ssaddr = {0};
    memcpy(&ssaddr, _pAddr, sizeof(sockaddr_in));
    m_vecDestAddrs.push_back(ssaddr);
}

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-06-30 20:15:46

你犯了两个错误:

  1. 您正在调用freeaddrinfo(),即使getaddrinfo()失败了。别干那事。
  2. 您假设res->ai_addr是一个sockaddr_storage*,但它不是。相反,它是一个sockaddr_in*,因为hints.ai_familyAF_INET (如果您使用了AF_INET6,它将是sockaddr_in6,而AF_UNSPEC可能是其中之一)。sockaddr_insockaddr_storage小,所以在将ai_addr数据复制到向量时访问内存是错误的。

试一试:

代码语言:javascript
运行
复制
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);
}

或者这个:

代码语言:javascript
运行
复制
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
EN

Stack Overflow用户

发布于 2014-06-30 14:00:41

来自文档,我的重点是:

成功的调用分配给该函数的内存必须与随后对freeaddrinfo的调用一起释放。

你没有注意到这条指令。你无条件地打电话给freeaddrinfo。只有当对freeaddrinfo的调用成功时,才必须调用getaddrinfo

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24491776

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档