我在C ++中有一些遗留代码,这些代码有一些我不明白的地方。 我在运行Windows XP的机器上运行Visual C ++ 2008 Express Edition。
代码使用一些Windows函数: GetAdaptersInfo和GetAdaptersAddressess。 我意识到这两个的最后一个参数是一个指向缓冲区大小的指针,因为它是in_out,所以可以在函数内改变。
我的问题是:这些function是否应该改变缓冲区的长度?
在我的代码中,每次调用这些函数时,缓冲区长度variables都被初始化为0,调用该函数之后,它仍然是0。
你的代码需要看起来像这样:
// 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!
编辑:另请参阅杰里米弗里斯纳的答案,为什么这个代码是不够的。
当然, @ RichieHindle的答案中的示例代码包含竞争条件….如果结构Windows想要返回的大小在第一次调用GetAdaptersInfo()之后但在第二次调用GetAdaptersInfo()之前增长,则第二次调用GetAdaptersInfo()将会失败,同时ERROR_BUFFER_OVERFLOW也会失败,你的函数将无法工作。
是的,这确实发生在现实生活中 – 我曾经遇到过这种事情。 如果您希望代码可靠,则需要在循环中调用GetAdaptersInfo(),根据需要多次增加缓冲区的大小,直到调用成功为止。
构建一个API必须有一个不太容易出错的方法……不幸的是,微软还没有找到它。 :^ P
的确,使用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!
这是一个错误还是我错过了什么?