getifaddrs比ioctl更适合获取接口列表,因其自动遍历ipv4/ipv6、正确处理别名接口(如eth0:0)、跳过非活动或无地址接口;而ioctl需手动解析二进制结构、易漏ipv6且对别名支持差。

getifaddrs 为什么比 ioctl 更适合获取接口列表
直接调用 getifaddrs 是 Linux/macOS 上获取网络接口最轻量、最可靠的方式,它自动遍历所有地址族(IPv4/IPv6)、处理别名接口(如 eth0:0)、跳过非活动或无地址接口,而 ioctl(SIOCGIFCONF) 需手动解析二进制结构、易漏掉 IPv6、且对别名支持差。
注意:Windows 不支持 getifaddrs,需用 GetAdaptersAddresses;本文聚焦 POSIX 系统。
调用 getifaddrs 后怎么安全遍历并提取关键字段
getifaddrs 返回单向链表,每个节点是 struct ifaddrs*,必须用 freeifaddrs 释放,否则内存泄漏。关键字段取法如下:
-
ifa->ifa_name:接口名(如"lo"、"enp0s3") -
ifa->ifa_flags:用IFF_UP和IFF_RUNNING判断是否启用并活跃 -
ifa->ifa_addr:指向sockaddr,需根据sa_family分支处理:AF_INET提取sin_addr,AF_INET6提取sin6_addr -
ifa->ifa_netmask:对应掩码,同样按地址族转换
示例片段(只取 IPv4 地址):
struct ifaddrs *ifaddr, *ifa;
if (getifaddrs(&ifaddr) == -1) {
perror("getifaddrs");
return;
}
for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_INET)
continue;
if (!(ifa->ifa_flags & IFF_UP) || !(ifa->ifa_flags & IFF_RUNNING))
continue;
struct sockaddr_in *sin = (struct sockaddr_in *)ifa->ifa_addr;
char ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &sin->sin_addr, ip, sizeof(ip));
printf("%s: %s\n", ifa->ifa_name, ip);
}
freeifaddrs(ifaddr);
常见崩溃点:空指针、未检查 sa_family、忘记 freeifaddrs
三个高频错误直接导致段错误或内存泄漏:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
-
ifa->ifa_addr可能为nullptr(例如某些虚拟接口),不判空就解引用必崩 - 未判断
ifa->ifa_addr->sa_family就强转sockaddr_in*,对 IPv6 接口会读错内存 - 调用
getifaddrs后忘记freeifaddrs,尤其在循环或长期运行服务中积累泄漏
建议封装检查宏:
#define VALID_INET_ADDR(ia) ((ia) && (ia)->ifa_addr && (ia)->ifa_addr->sa_family == AF_INET)
跨平台兼容性与替代方案提示
如果代码需同时跑 Linux/macOS/Windows:getifaddrs 在 macOS 上可用,但部分旧版嵌入式 libc(如 uClibc)不提供;Windows 必须用 GetAdaptersAddresses,返回结构完全不同,无法简单替换。
更稳妥的跨平台做法是抽象一层接口,Linux/macOS 走 getifaddrs,Windows 走 GetAdaptersAddresses,并统一返回结构体(含 name、addr、netmask、flags 字段)。
别指望 getifaddrs 返回“主 IP”或“默认路由接口”——它只罗列配置,选哪个用得结合路由表或业务逻辑判断。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










