GetAdaptersAddresses 返回 ERROR_BUFFER_OVERFLOW 时未更新缓冲区大小,是因为首次调用前未将 *pOutBufLen 初始化为0或传入了无效指针;正确做法是声明 ULONG size = 0 并传 &size,仅当返回该错误时才按新 size 分配字节缓冲区并重试。

为什么 GetAdaptersAddresses 返回 ERROR_BUFFER_OVERFLOW 却没填缓冲区?
这是最常卡住的起点:调用一次 GetAdaptersAddresses 后直接检查返回值,发现是 ERROR_BUFFER_OVERFLOW,但传入的 ULONG *size 没被更新,或更新后再次分配仍失败。根本原因是——你没传入有效的 size 地址,或者传了但没初始化为 0(Windows 要求首次调用时 *size == 0 才触发“先告知所需大小”的逻辑)。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 首次调用前,声明
ULONG size = 0,传入&size;不要传nullptr或未初始化变量 - 检查返回值是否为
ERROR_BUFFER_OVERFLOW(不是ERROR_INSUFFICIENT_BUFFER,后者是旧 APIGetAdaptersInfo的) - 仅当返回该错误时,才用新
size分配内存(注意:是字节长度,不是结构体个数) - 第二次调用必须用新分配的缓冲区 + 正确的
size值,否则可能崩溃或静默截断
如何安全遍历 IP_ADAPTER_ADDRESSES 链表并提取关键字段?
GetAdaptersAddresses 返回的是单向链表,每个节点含适配器名、描述、IPv4/IPv6 地址、网关、DNS 等。但字段嵌套深、指针多,容易访问空指针或越界。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 用
for (auto* ptr = result; ptr; ptr = ptr->Next)遍历,别用下标 - 取适配器名称用
ptr->AdapterName(ANSI 字符串,可用于ConvertStringSidToSddl等系统调用),取显示名用ptr->FriendlyName(宽字符,需wprintf) - 获取 IPv4 地址:遍历
ptr->FirstUnicastAddress链表,检查addr->Address.lpSockaddr->sa_family == AF_INET,再强转为sockaddr_in*提取sin_addr - 跳过回环、隧道、禁用适配器:检查
ptr->OperStatus != IfOperStatusUp或ptr->IfType == IF_TYPE_SOFTWARE_LOOPBACK
为什么获取到的 DNS 服务器地址是空,或 FirstDnsServerAddress 指向无效内存?
IP_ADAPTER_DNS_SERVER_ADDRESS 是独立链表,不和地址列表混在一起。常见错误是直接解引用 adapter->FirstDnsServerAddress 而不校验其非空,或忽略它也是单向链表(不是数组)。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 必须先判空:
if (ptr->FirstDnsServerAddress),再遍历其Next字段 - 每个节点的
Address.lpSockaddr才是真实地址,sa_family决定是 IPv4 还是 IPv6 - 注意:DNS 地址可能来自策略(如组策略配置),不一定反映
ipconfig /all中的“DNS Servers”行——后者还包含连接特定 DNS 后缀,需查ptr->DnsSuffix - 若需完整 DNS 配置(含后缀、搜索列表),应同时读取
ptr->FirstDnsSuffix和ptr->ConnectionSpecificSuffix
编译链接时提示 unresolved external symbol GetAdaptersAddresses 怎么办?
这不是代码逻辑问题,而是工程配置缺失。该函数在 Iphlpapi.lib 中,且需 Windows XP SP1+,但默认项目可能没链接或宏定义不对。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 确保源文件包含
#include <iphlpapi.h></iphlpapi.h>,并在#include前定义WIN32_LEAN_AND_MEAN(避免 winsock 冲突) - 链接器输入中加入
Iphlpapi.lib(MSVC:项目属性 → 链接器 → 输入 → 附加依赖项) - 检查目标平台:若项目设为
Windows SDK 8.1及以上,函数可用;若设为太老的 SDK(如 7.0),需手动加#pragma comment(lib, "Iphlpapi.lib") - 不要混用
winsock.h和winsock2.h—— 后者必须在前者之前,否则类型重定义报错
真正麻烦的从来不是调用一次 API,而是处理 OperStatus 和 IfType 的组合状态(比如“已启用但无媒体连接”的适配器是否算有效)、Unicode 宽字符转换、以及不同 Windows 版本对 Ipv6IfIndex 等字段的填充差异。这些细节不会报错,但会让拿到的数据和系统设置界面对不上。


















