c - 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”覆盖。但在那之后堆仍然有效。所以我不知道从哪里开始调试这个。会不会是其他缓冲区或结构在某处溢出?
解决方案
res
每次执行 line 时,您的 while (res) 都会将指针移动到原始节点以外的其他节点res = res->ai_next;
,但是最后您FreeAddrInfo(res);
使用修改后的指针调用,而不是通过 GetAddrInfo 分配的指针。
另外,虽然你没有提供lookup_host函数的开始,但是假设一个inout是ptr,你是从分配的emory中将它设置为sin_addr的地址,然后在函数结束时释放内存,所以它可能被其他东西使用。
推荐阅读
- android - 活动中除了一个片段之外的所有片段都是空白的
- java - 每次都需要 HttpPost 中的授权吗?
- r - 如何循环数千个线性回归并提取 P 值
- arrays - 猫鼬找到返回的未定义文档
- python - Scrapy 不抓取所有结果
- javascript - JavaScript 数组排序与混合值类型 - 寻找适当的比较函数
- c# - 在 Excel 顶部插入记录
- python - 如何使用 launchpadlib 获取特定 Ubuntu 系列的软件包和版本的完整列表
- python - Scrapy如何提取您未选择的字段的文本
- batch-file - 如何在批处理脚本中使用服务的显示名称删除 Windows 服务?