首次调用GetAdaptersAddresses返回ERROR_BUFFER_OVERFLOW是正常流程,需先传NULL和初始化为0的ULONG指针获取所需字节数,再malloc分配内存并重试;必须用FreeMibTable释放内存,遍历FirstUnicastAddress链表提取IPv4/IPv6地址。

GetAdaptersAddresses 返回 ERROR_BUFFER_OVERFLOW 怎么办
调用 GetAdaptersAddresses 第一次总是失败并返回 ERROR_BUFFER_OVERFLOW,这不是错误,是 Windows 的标准流程:你需要先调用一次获取所需缓冲区大小,再分配足够内存重试。
- 第一次传入
NULL作为pAdapterAddresses,SizePointer必须非空,函数会把所需字节数写入其中 - 用
malloc或std::vector<byte></byte>分配该大小的缓冲区(别直接用sizeof(IP_ADAPTER_ADDRESSES)硬编码) - 第二次调用时传入该缓冲区指针和大小,此时才真正填充数据
- 注意:两次调用的
Flags参数必须一致,否则大小计算可能不匹配
如何遍历所有 IPv4 和 IPv6 地址(不止主地址)
GetAdaptersAddresses 返回的是链表结构,每个 IP_ADAPTER_ADDRESSES 节点自带一个 FirstUnicastAddress 链表,里面包含该网卡所有配置的单播地址(包括 DHCP 分配的、手动添加的、IPv4/IPv6 各自的地址)。
- 不要只取
Ipv4Address字段(那是过时的GetAdaptersInfo用法),它只存第一个 IPv4 地址且不支持 IPv6 - 逐个遍历
pAddr->FirstUnicastAddress链表,检查Address.lpSockaddr->sa_family是AF_INET还是AF_INET6 - 用
getnameinfo或inet_ntop将sockaddr转为字符串;对 IPv6 注意处理 scope_id(但通常显示时可忽略) - 同一块网卡可能有多个 IPv4(比如绑定多个子网),也常见 IPv6 的 link-local + global 组合
哪些网卡会被过滤掉?如何控制可见范围
默认情况下 GetAdaptersAddresses 会跳过“未连接”或“已禁用”的适配器,但行为受 Flags 参数严格控制。
- 加
GAA_FLAG_INCLUDE_PREFIX才能拿到子网掩码(通过IP_ADAPTER_UNICAST_ADDRESS_LH::PrefixOrigin等字段) - 加
GAA_FLAG_INCLUDE_ALL_INTERFACES可包含虚拟网卡(如 Hyper-V、Docker、WSL2 的 vEthernet)、环回适配器(127.0.0.1)等,默认不返回 - 不加
GAA_FLAG_SKIP_DNS_SERVER时,FirstDnsServerAddress链表才有效;但 IP 地址本身不受此标志影响 - 如果发现某张物理网卡没出现,先用
ipconfig /all确认其状态是否为 “Media disconnected”,Windows 默认不返回这类适配器
内存泄漏和结构体生命周期要注意什么
GetAdaptersAddresses 分配的内存必须用 FreeMibTable 释放(不是 free 或 delete),且只能释放顶层指针 —— 所有嵌套链表(FirstUnicastAddress、FirstAnycastAddress 等)都由系统统一管理。
立即学习“C++免费学习笔记(深入)”;
- 切勿对链表节点调用
free,否则程序可能崩溃或后续调用出错 - 若使用
std::vector<byte></byte>管理缓冲区,记得在调用FreeMibTable前把原始指针保存下来(因为 vector 可能移动内存) - 多线程环境下,每次调用应独占缓冲区;不要复用同一块内存跨线程传参
- Windows 7+ 推荐用
IP_ADAPTER_ADDRESSES_LH类型(而非旧版IP_ADAPTER_ADDRESSES),字段更全,兼容性更好


















