我在使用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支持。
答案 0 :(得分:1)
来自documentation,强调:
通过成功调用此函数分配的内存必须在随后调用freeaddrinfo时释放。
你没有听从这个指示。您无条件致电freeaddrinfo
。只有在freeaddrinfo
的来电成功时,您才能致电getaddrinfo
。
答案 1 :(得分:1)
你犯了两个错误:
即使freeaddrinfo()
失败,您也在呼叫getaddrinfo()
。不要那样做。
您假设res->ai_addr
是sockaddr_storage*
,但事实并非如此。这是sockaddr_in*
,因为hints.ai_family
是AF_INET
(如果您使用AF_INET6
,则会sockaddr_in6
而AF_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);
}
数据复制到矢量时错误地访问了内存。
请改为尝试:
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}}