GetAdaptersInfo 和 GetAdaptersAddressess BufferLength 参数
Posted
技术标签:
【中文标题】GetAdaptersInfo 和 GetAdaptersAddressess BufferLength 参数【英文标题】:GetAdaptersInfo and GetAdaptersAddressess BufferLength Param 【发布时间】:2010-11-07 09:46:38 【问题描述】:我这里有一些 C++ 遗留代码,这些代码做了一些我不理解的事情。我在运行 Windows XP 的机器上以 Visual C++ 2008 Express Edition 运行它。
代码使用了一些 Windows 函数:GetAdaptersInfo 和 GetAdaptersAddressess。我意识到这两个参数的最后一个参数是指向缓冲区大小的指针,并且由于它是 in_out,它可以在函数内更改。
我的问题是:这些函数是否应该改变缓冲区长度?
在我的代码中,每次调用这些函数时,缓冲区长度变量都会初始化为零,调用函数后,它仍然是0。
【问题讨论】:
【参考方案1】:您的代码需要如下所示:
// First get the desired size.
unsigned long outBufLen = 0;
DWORD dwResult = GetAdaptersInfo(NULL, &outBufLen);
if (dwResult == ERROR_BUFFER_OVERFLOW) // This is what we're expecting
// Now allocate a structure of the requried size.
PIP_ADAPTER_INFO pIpAdapterInfo = (PIP_ADAPTER_INFO) malloc(outBufLen);
dwResult = GetAdaptersInfo(pIpAdapterInfo, &outBufLen);
if (dwResult == ERROR_SUCCESS)
// Yay!
编辑:另请参阅 Jeremy Friesner 的回答,了解为什么此代码还不够。
【讨论】:
所以 GetAdaptersInfo 获取 pIpAdapterInfo 元素在第一次调用中的大小,然后在第二次调用中实际获取适配器信息?那很有意思。感谢您的澄清。 是的。填充缓冲区的 Windows API 以这种方式工作是很常见的。【参考方案2】:确实,使用 Visual Studio 6,我曾经通过以下方式获取适配器的数量:
DWORD drc = GetAdaptersInfo(NULL, &(Buflen = 0L));
if (drc == ERROR_BUFFER_OVERFLOW)
n = Buflen / sizeof(IP_ADAPTER_INFO);
没关系,例如 2 个适配器,Buflen 设置为 1280,sizeof(IP_ADAPTER_INFO)
设置为 640。
现在我使用 Visual C++ 2008 Express,结果被截断,因为该函数仍将 Buflen 设置为 1280,但 sizeof(IP_ADAPTER_INFO)
的值现在是 648!
这是一个错误还是我遗漏了什么?
【讨论】:
我知道这是一个老问题,但我在 MinGW 构建中遇到了同样的问题。所以也许这对将来的某人有帮助。原因是time_t 类型的大小。见msdn.microsoft.com/en-us/library/windows/desktop/… 重要部分:“使用 Visual Studio 2005 及更高版本时,time_t 数据类型默认为 8 字节数据类型,而不是 32 位上用于 LeaseObtained 和 LeaseExpires 成员的 4 字节数据类型平台。要在 32 位平台上正确使用 IP_ADAPTER_INFO 结构,请在编译应用程序时定义 _USE_32BIT_TIME_T(例如,使用 -D _USE_32BIT_TIME_T 作为选项)以强制 time_t 数据类型为 4 字节数据类型。"【参考方案3】:当然,@RichieHindle's answer 中的示例代码包含一个竞争条件......如果 Windows 想要返回的结构的大小在第一次调用 GetAdaptersInfo() 之后但在第二次调用 GetAdaptersInfo() 之前增长,对 GetAdaptersInfo() 的第二次调用也将失败并显示 ERROR_BUFFER_OVERFLOW,并且您的函数将无法正常工作。
是的,这确实发生在现实生活中——我也遇到过。如果您希望代码可靠,则需要在循环中调用 GetAdaptersInfo(),根据需要多次增加缓冲区大小,直到调用成功。
必须有一种不太容易出错的方法来构造 API……不幸的是,微软还没有找到它。 :^P
【讨论】:
+1 好点。哇,你被那个抓住真是太不幸了!以上是关于GetAdaptersInfo 和 GetAdaptersAddressess BufferLength 参数的主要内容,如果未能解决你的问题,请参考以下文章
GetAdaptersInfo & GetAdaptersAddresses
请教下为何MSDN里查不到GetAdaptersInfo这个API,
vb.net 第一节 获取本机网络适配器的信息 GetAdaptersInfo
如何在 C++ 中读取 Windows 默认网关 IP 地址
RecyclerView ItemTouchHelper getAdapterPosition() 在快速滑动时返回错误值