首页 > 解决方案 > C addrinfo 结构已损坏。但是堆仍然有效

问题描述

我尝试创建一个套接字并连接到远程主机。我使用 GetAddrInfo 从域解析远程主机。哪个工作正常。通话后,我得到了一个具有正确值的工作 addrinfo 结构。但在某些情况下,结构在调用 connect() 之前就已损坏。

struct addrinfoW sa = { 0 };
ZeroMemory(&sa, sizeof(sa));
lookup_host(host, &sa);

int sock = 0;
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == -1) {
    return -1;
}
HeapValidate(GetProcessHeap(), HEAP_NO_SERIALIZE, NULL);
if(connect(sock, sa->ai_addr, sa->ai_addrlen) < 0) {
    HeapValidate(GetProcessHeap(), HEAP_NO_SERIALIZE, NULL);
#ifdef _DEBUG
    printf("Error: %d\n", GetLastError());
#endif // _DEBUG

    return -2;
}

其中lookup_host定义为:

struct addrinfoW hints = { 0 };
struct addrinfoW *res;
int errcode;
ZeroMemory(&hints, sizeof(struct addrinfoW));
//ZeroMemory(res, sizeof(struct addrinfo));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags |= AI_CANONNAME;
errcode = GetAddrInfo(host, L"80", &hints, &res);//GetAddrInfoExW(L"google.de", L"80", NS_ALL, NULL, &hints, &res, NULL, NULL, NULL, NULL);  //GetAddrInfoEX(L"google.de", L"80", &hints, &res);
win_free(mbHost);
if (errcode != 0)
{
    //perror("getaddrinfo");
    return -1;
}
void *ptr = 0;
while (res)
{
    switch (res->ai_family)
    {
    case AF_INET:
        ptr = &((struct sockaddr_in *) res->ai_addr)->sin_addr;
        break;
    case AF_INET6:
        ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
        break;
    }
    CopyMemory(out, res, sizeof(struct addrinfoW));
    break;
    res = res->ai_next;
}
FreeAddrInfo(res);

所以这在我的四核 Win10 笔记本电脑上运行良好。但是,如果我添加例如

MessageBoxA(NULL, "After sock", "HTTP", MB_ICONWARNING|MB_CANCELTRYCONTINUE | MB_DEFBUTTON2);

在 connect() 调用之前调用并检查调试器中的 addrinfo 结构,它已损坏。例如,有时我可以看到应该是“google.com”的ai_canonname 被“After Sock”覆盖。但在那之后堆仍然有效。所以我不知道从哪里开始调试这个。会不会是其他缓冲区或结构在某处溢出?

标签: cwinsockmemory-corruption

解决方案


res每次执行 line 时,您的 while (res) 都会将指针移动到原始节点以外的其他节点res = res->ai_next;,但是最后您FreeAddrInfo(res);使用修改后的指针调用,而不是通过 GetAddrInfo 分配的指针。

另外,虽然你没有提供lookup_host函数的开始,但是假设一个inout是ptr,你是从分配的emory中将它设置为sin_addr的地址,然后在函数结束时释放内存,所以它可能被其他东西使用。


推荐阅读