【转载】GetAdaptersInfo函数在64位系统上返回ERROR_NOACCESS的有关问题

From:http://www.educity.cn/wenda/351190.html

GetAdaptersInfo函数在64位系统下返回ERROR_NOACCESS的问题

  实际应用中一个程序在长时间运行后内存占用较高时发生崩溃,从dump信息中,发现GetAdaptersInfo函数返回了一个奇怪的错误码998(ERROR_NOACCESS),百度搜索不到相关的信息。MSDN上GetAdaptersInfo函数的错误码正常情况下只有5种。并且一共发生的两次崩溃都出现在一台Win7 64位机器上,其他测试机器均正常。

  有问题的代码如下:

  void GetMacAddr(char *buf) { BOOL bNewState = TRUE; //PIP_ADAPTER_INFO结构体指针存储本机网卡信息 PIP_ADAPTER_INFO pIpAdapterInfo = new(std::nothrow) IP_ADAPTER_INFO; if (pIpAdapterInfo == NULL) { return; } //得到结构体大小,用于GetAdaptersInfo参数 unsigned long stSize = sizeof(IP_ADAPTER_INFO); //调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量;其中stSize参数既是一个输入量也是一个输出量 ULONG ulRel = GetAdaptersInfo (pIpAdapterInfo, &stSize); if (ERROR_BUFFER_OVERFLOW == ulRel) { bNewState = FALSE; delete pIpAdapterInfo; //重新申请内存空间用来存储所有网卡信息 pIpAdapterInfo = (PIP_ADAPTER_INFO)new(std::nothrow) BYTE[stSize]; if (pIpAdapterInfo == NULL) { return; } //再次调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量 ulRel = GetAdaptersInfo (pIpAdapterInfo, &stSize); } string strIpMac; if (ERROR_SUCCESS==ulRel) { //输出网卡信息 //可能有多网卡,因此通过循环去判断 PIP_ADAPTER_INFO pIpAdapterInfoTmp = pIpAdapterInfo; while (pIpAdapterInfoTmp != NULL) { char szMac[10] = {0}; for (UINT i =0; i < pIpAdapterInfoTmp->AddressLength; i++) { if (i==pIpAdapterInfoTmp->AddressLength-1) { _snprintf_s(szMac, 10, "%02x;", pIpAdapterInfoTmp->Address[i]); strIpMac += szMac; } else { _snprintf_s(szMac, 10, "%02x-", pIpAdapterInfoTmp->Address[i]); strIpMac += szMac; } } pIpAdapterInfoTmp = pIpAdapterInfoTmp->Next; } } //释放内存空间 if (pIpAdapterInfo != NULL) { if (bNewState == FALSE) { delete[] pIpAdapterInfo; } else { delete pIpAdapterInfo; } } if (strIpMac[strIpMac.length()-1] == ';') { strIpMac[strIpMac.length()-1] = '\0'; } sprintf(buf,"%s",strIpMac.c_str()); return; }

  Return code

  Description

  ERROR_BUFFER_OVERFLOW

  The buffer to receive the adapter information is too small. This value is returned if the buffer size indicated by the pOutBufLen parameter is too small to hold the adapter information or the pAdapterInfo parameter was a NULL pointer. When this error code is returned, the pOutBufLen parameter points to the required buffer size.

  ERROR_INVALID_DATA

  Invalid adapter information was retrieved.

  ERROR_INVALID_PARAMETER

  One of the parameters is invalid. This error is returned if the pOutBufLen parameter is a NULL pointer, or the calling process does not have read/write access to the memory pointed to by pOutBufLen or the calling process does not have write access to the memory pointed to by the pAdapterInfo parameter.

  ERROR_NO_DATA

  No adapter information exists for the local computer.

  ERROR_NOT_SUPPORTED

  The GetAdaptersInfo function is not supported by the operating system running on the local computer.

  Other

  If the function fails, use FormatMessage to obtain the message string for the returned error.

  所以我们将问题锁定为Win7 64位机器,内存占用高,GetAdaptersInfo函数返回998错误。

  为此我们编写了一个测试程序,创建两个线程,一个线程不断申请内存,一次申请500KB,另外一个线程循环调用GetAdaptersInfo函数,直到返回998错误。

  测试结果验证了我们的猜测。

  自此原因查明,程序代码在返回998的时候未做判断,对申请的内存进行了delete操作引起了崩溃,而998代表ERROR_NOACCESS即不能访问,所以应该进行判断。

  在这个问题解决后不久,微软的Bug报告及建议网站上找到了一篇文章,$amp;<lt;$strong>GetAdaptersAddresses API incorrectly returns no adapters for a process with high memory consumption>, rrectly-returns-no-adapters-for-a-process-with-high-memory-consumption.一位国外程序员同样重现了此问题,但微软方面至今未给出解决方案,只确认了这属于Windows操作系统的一个Bug。在他的描述中更详细的指明了发生条件:

  1.32-bit application

  2.64-bit operating system or /3GB feature enabled on 32-bit operating system

  3.hosting process is linked with /LARGEADDRESSAWARE flag or has otherwise set it in binary header

  4.over 2GB of RAM (in terms of Private Bytes/Virtual Size performance counters) consumed by the hosting process

  即32位程序,运行在64位操作系统,超过2GB的进程内存占用,同样佐证了我们的猜测。

posted @ 2015-11-16 12:29  ourran  阅读(868)  评论(0编辑  收藏  举报