使用 memset 和 freeaddrinfo 会导致双重释放或损坏错误
Posted
技术标签:
【中文标题】使用 memset 和 freeaddrinfo 会导致双重释放或损坏错误【英文标题】:using memset and freeaddrinfo causes the double free or corruption error 【发布时间】:2021-07-18 15:40:03 【问题描述】:src.cpp
#include <iostream>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
int main()
struct addrinfo hints, *servinfo;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
getaddrinfo(NULL, "1560", &hints, &servinfo);
freeaddrinfo(&hints);
我用gdb找出错误发生在哪里,它发生在memset 但是当我注释掉对 freeaddrinfo() 的调用时,它没有给出错误并且可以正常工作!
我正在运行 Ubuntu 20.04.2 内核 5.8.0-55-generic
编辑: 正如您指出的,我应该给 freeaddrinfo 一个由 getaddrinfo 提供的列表,当我将 servinfo 传递给 freeaddrinfo 时,它会给出以下错误
double free or corruption (out)
[1] 4123 abort (core dumped) ./a.out
编辑 2:谢谢,在编辑问题时,我忘记用 servinfo 替换 &hints,并认为我已经替换了它,很抱歉给您带来不便,我的愚蠢值得一票否决。
【问题讨论】:
你可以试试valgrind 【参考方案1】:freeaddrinfo
函数需要一个指向由getaddrinfo
创建的addrinfo
结构列表的指针。
你传递的指针不是这样的结构列表,所以会导致函数内部的未定义行为
getaddrinfo
函数很可能使用malloc
分配结构,freeaddr
函数将它们传递给free
。
您不能传递指向free
的指针,而该指针不是由malloc
(或其他相关函数,如calloc
或realloc
)返回的。
您不会为hints
动态分配空间。您在堆栈上分配它。它不应该传递给freeaddrinfo
,只有结果(在你的情况下是servinfo
)应该是。
【讨论】:
正如你所指出的,我应该给 freeaddrinfo 一个由 getaddrinfo 提供的列表,当我将 servinfo 传递给 freeaddrinfo 时,它会给出双重免费或损坏错误:( @HPSmash77 只是不要打电话给freeaddrinfo(&hints)
?作为一般提示:当您在调用包含术语free
的任何函数时需要使用指向(或地址)运算符&
时,您应该将其视为您做错了什么的标志。
【参考方案2】:
freeaddrinfo(&hints);
这是预期的行为(行为未定义的方式;而不是您可以依赖此行为的方式)。您只能将getaddrinfo
创建的结构传递给freeaddrinfo
。您没有使用getaddrinfo
创建&hints
。不要将hints
传递给freeaddrinfo
。
一个固定的例子:
addrinfo hints
.ai_flags = AI_PASSIVE,
.ai_family = AF_UNSPEC,
.ai_socktype = SOCK_STREAM,
;
addrinfo* result;
int err = getaddrinfo(nullptr, "12345", &hints, &result);
if (err)
std::cout << "getaddrinfo: " << gai_strerror(err);
std::exit(EXIT_FAILURE);
else
// use it here
freeaddrinfo(result); // pay particular attention to this
我把它换成了 freeaddrinfo(servinfo);
您的新示例仍然有freeaddrinfo(&hints)
,但也有freeaddrinfo(servinfo)
。如果您将前者替换为后者,那么您将调用freeaddrinfo(servinfo)
两次。释放后,您不能使用无效的servinfo
,包括第二次将其传递给freeaddrinfo
。类似的规则适用于std::free
。
【讨论】:
正如你所指出的,我应该给 freeaddrinfo 一个由 getaddrinfo 提供的列表,当我将 servinfo 传递给 freeaddrinfo 时,它会给出双重免费或损坏错误:( @HPSmash77 你必须删除freeaddrinfo(&hints);
这一行
我把它换成了 freeaddrinfo(servinfo);然后它给出了我在上一条评论中指定的错误
@HPSmash77 见编辑。另请参阅我的示例。
哦!抱歉,编辑代码时忘记这样做了:(以上是关于使用 memset 和 freeaddrinfo 会导致双重释放或损坏错误的主要内容,如果未能解决你的问题,请参考以下文章