C语言遍历ai_next链表时空指针检查失效触发段错误
段错误根因排查与修复方案
核心错误点
- 字段赋值混淆导致配置非法
你在初始化hints结构体时,错误地将本该赋值给ai_flags字段的AI_PASSIVE常量,重复赋值给了ai_family字段:hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_family = AI_PASSIVE; // 致命错误:覆盖了合法的地址族配置AI_PASSIVE是地址配置的标志位,不属于地址族字段的合法取值。这次赋值会把之前配置的AF_UNSPEC覆盖成AI_PASSIVE对应的数值,直接给getaddrinfo传入非法参数,导致函数调用直接失败。 - 缺少
getaddrinfo返回值校验
你直接调用完getaddrinfo就使用输出指针res,完全没有检查函数执行结果。一旦getaddrinfo调用失败,它不会给res分配合法的链表内存,也不会主动将res设置为NULL,此时res是栈上的未初始化野指针,值为随机垃圾数。
这种情况下你写的addr != NULL判断完全失效——因为野指针本身不等于NULL,循环会直接进入,解引用指向非法内存的指针时就会触发段错误。
正确的修复代码
#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <string.h> #include <errno.h> #define MYPORT "6161" int main() { struct addrinfo hints, *res = NULL; // 主动初始化res为NULL,避免野值问题 int gai_ret; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; // 把AI_PASSIVE放到正确的ai_flags字段 // 必须检查getaddrinfo的返回值 gai_ret = getaddrinfo(NULL, MYPORT, &hints, &res); if (gai_ret != 0) { fprintf(stderr, "getaddrinfo调用失败: %s\n", gai_strerror(gai_ret)); return 1; } struct addrinfo *addr; for (addr = res; addr != NULL; addr = addr->ai_next) { printf("Here's one addr!\n"); // 补充换行符避免输出缓冲不显示 } // 遍历完成后必须释放getaddrinfo分配的链表内存,避免泄漏 freeaddrinfo(res); return 0; }
补充说明
你之前用远程地址的代码运行正常,本质是当时没有出现字段赋值错位的问题,getaddrinfo能正常返回合法的地址链表。本次的段错误和配置本机/远程地址没有关系,完全是赋值笔误加缺少错误校验导致的。
内容的提问来源于stack exchange,提问作者Dylan Landry
相关产品推荐
相关产品推荐

