C++获取网络接口信息偶发段错误、统计结果异常问题咨询
Linux下C++获取网卡信息两类异常的根因说明
偶发段错误(Segmentation Fault)的核心诱因
- 指针访问前未做合法性校验:调用
getifaddrs返回的网卡链表中,部分虚拟网卡(容器veth、tun/tap、网桥附属接口)的ifa_addr/ifa_netmask指针可能为空,或是地址族与预期不符(比如不是AF_INET/AF_PACKET),直接将指针强转为sockaddr_in/sockaddr_ll访问内部成员,就会访问非法内存。这类问题触发概率和系统当前运行的网卡数量、状态强相关,所以表现为随机崩溃。 - 内存/缓冲区越界:查询MAC地址使用
ifreq结构时,未预留足够的地址存储长度;或是解析/proc/net/dev内容做字符串处理时,未手动补字符串结束符\0,遇到长度超过15字节的长网卡名(容器生成的虚拟网卡名普遍较长)时,会写穿栈/堆缓冲区,破坏相邻内存的指针、返回地址,触发随机崩溃。 - 资源句柄未校验:调用
socket()创建ioctl用的套接字时,若文件描述符耗尽、权限不足会返回-1,代码未判断返回值直接将-1作为有效fd传入ioctl,会导致内核态拷贝数据到非法用户态地址,触发段错误。 - 链表/消息遍历逻辑错误:如果用netlink套接字获取网卡信息,遍历返回的消息链表时未做
NLMSG_OK合法性校验,计算下一条消息的偏移量错误,会读到非消息区域的垃圾内存,解引用时崩溃。
网卡统计值无规律异常的核心诱因
- 结构体不匹配、未初始化:读取网卡统计数据时,如果用旧版32位的
rtnl_link_stats结构接收内核返回的64位rtnl_link_stats64结构,会因为结构长度不匹配只读到部分数据;如果定义接收统计值的结构体前没有用memset清零,栈上残留的垃圾内存值会被当成有效统计值返回,每次运行栈内存状态不同,数值就会乱跳。 - 解析逻辑偏移错误:解析
/proc/net/dev文件时,如果未正确跳过文件头的两行说明,或是字段分割时没处理网卡名后的冒号、多列空格的情况,调用字符串转整数函数时会读到非数字内容,返回随机异常值;多队列网卡的统计值按队列分散存储,若代码错误读取了队列偏移位置的内容,不同运行时队列状态变化也会导致数值异常。 - 字节序处理错误:部分ioctl、netlink返回的统计字段为网络字节序,未调用
ntohl/ntohll转为主机字节序直接读取,会得到和实际值偏差极大的结果。
快速排查建议:编译时添加
-g -fsanitize=address编译选项运行,地址消毒工具会直接定位到内存越界、非法指针访问的具体代码行;排查统计值问题时,先给所有存储统计值的结构体做全零初始化,逐字段和cat /proc/net/dev输出的官方统计值做偏移核对即可。
内容的提问来源于stack exchange,提问作者mah454
相关产品推荐
相关产品推荐

