使用 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(或其他相关函数,如 callocrealloc)未返回的指针。


您没有为 hints 动态分配 space。你在堆栈上分配它。它不应传递给 freeaddrinfo,只有结果(在您的情况下为 servinfo)应该是。