使用 memset 和 freeaddrinfo 导致双重释放或损坏错误
using memset and freeaddrinfo causes the double free or corruption error
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,以为我已经替换了它,很抱歉给您带来不便,我的愚蠢应该得到每一点反对票。
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
}
I replaced it with freeaddrinfo(servinfo);
您的新示例仍然有 freeaddrinfo(&hints)
,还有 freeaddrinfo(servinfo)
。如果您将前者替换为后者,那么您将调用 freeaddrinfo(servinfo)
两次。释放后,您不能使用无效的 servinfo
,包括将其再次传递给 freeaddrinfo
。适用于 std::free
.
的类似规则
freeaddrinfo
function expects a pointer to a list of addrinfo
structures created by getaddrinfo
.
您传递的指针不是指向这样的结构列表,因此这将导致函数内部出现未定义的行为
getaddrinfo
函数很可能使用malloc
分配结构,freeaddr
函数将它们传递给free
。
您不能将 free
的指针传递给 malloc
(或其他相关函数,如 calloc
或 realloc
)未返回的指针。
您没有为 hints
动态分配 space。你在堆栈上分配它。它不应传递给 freeaddrinfo
,只有结果(在您的情况下为 servinfo
)应该是。
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,以为我已经替换了它,很抱歉给您带来不便,我的愚蠢应该得到每一点反对票。
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
}
I replaced it with freeaddrinfo(servinfo);
您的新示例仍然有 freeaddrinfo(&hints)
,还有 freeaddrinfo(servinfo)
。如果您将前者替换为后者,那么您将调用 freeaddrinfo(servinfo)
两次。释放后,您不能使用无效的 servinfo
,包括将其再次传递给 freeaddrinfo
。适用于 std::free
.
freeaddrinfo
function expects a pointer to a list of addrinfo
structures created by getaddrinfo
.
您传递的指针不是指向这样的结构列表,因此这将导致函数内部出现未定义的行为
getaddrinfo
函数很可能使用malloc
分配结构,freeaddr
函数将它们传递给free
。
您不能将 free
的指针传递给 malloc
(或其他相关函数,如 calloc
或 realloc
)未返回的指针。
您没有为 hints
动态分配 space。你在堆栈上分配它。它不应传递给 freeaddrinfo
,只有结果(在您的情况下为 servinfo
)应该是。