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的进程内存占用,同样佐证了我们的猜测。

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

  1. [转]C#程序无法在64位系统上运行之.NET编译的目标平台

    今天将编译的C#的exe拷贝到测试机上(Win7_64bit),一运行就挂了,提示“stop working”,一开始怀疑测试机上没有安装.net framework框架,追究半天原来是编译的目标平台 ...

  2. 【转】将 Linux 应用程序移植到 64 位系统上

    原文网址:http://www.ibm.com/developerworks/cn/linux/l-port64.html 随着 64 位体系结构的普及,针对 64 位系统准备好您的 Linux® 软 ...

  3. 在64位系统上不能安装Matlab notebook的解决方案

    在64位系统上不能安装Matlab notebook的解决方案 过程分解 第一步:安装好matlab(附:Matalab R2015a界面) 第二步:在matlab中执行命令 >>note ...

  4. 在window server 2008 64位系统上 发布网站的过程中遇到的问题(转)

    发布网站的过程如下: 1.安装数据库系统2.建立数据库,执行sql3.安装iis4.在本地机子上发布网站5.把发布好的东西拷贝到IIS上 1.安装数据库系统: 出现错误:必须使用角色管理工具 安装或配 ...

  5. 在window server 2008 64位系统上 发布网站的过程中遇到的问题

    发布网站的过程如下: 1.安装数据库系统2.建立数据库,执行sql3.安装iis4.在本地机子上发布网站5.把发布好的东西拷贝到IIS上 1.安装数据库系统: 出现错误:必须使用角色管理工具 安装或配 ...

  6. 如何在64位系统上安装SQL Server 2000

    如何在64位系统上安装SQL Server 2000? 现在用SQL Server 2000数据库的人少了吧?大都是SQL Server 2005/2008了.不过还是有需求的,今天一朋友就让我在他的 ...

  7. Win7 64位系统上配置使用32位的Eclipse(转)

    Win7 64位系统上配置使用32位的Eclipse 博客分类: Eclipse eclipse  最近工作电脑换成了64位的win7系统,之前个人电脑上安装的jdk和Eclipse都是32位的.而新 ...

  8. 32位程序在64位系统上获取系统安装时间(要使用KEY_WOW64_64KEY标记)

    众所周知,取系统的安装时间可取注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion的子项InstallDate,此值是个 ...

  9. 使用visual c++ 2005远程调试64位系统上32位与64位程序

    一直都挺喜欢使用visual c++远程调试代码,它能展现给我们当时代码执行最真实的情景,今天有时间记录一下,以免以后忘了. 远程调试需要在被调试端安装服务器,对于visual c++ 2005来说调 ...

随机推荐

  1. Spark机器学习4·分类模型(spark-shell)

    线性模型 逻辑回归--逻辑损失(logistic loss) 线性支持向量机(Support Vector Machine, SVM)--合页损失(hinge loss) 朴素贝叶斯(Naive Ba ...

  2. NOIP 马拦过河卒

    描述 棋盘上A点有一个过河卒,需要走到目标B点.卒行走的规则:可以向下.或者向右.同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点.因此称之为“马拦过河卒”. 棋盘 ...

  3. Java 泛型<T> T 与 T的用法

    T 与 T 比较 T是Type的首字母缩写: T 表示"返回值"是一个泛型,传递什么类型,就返回什么类型:而单独的"T"表示限制传递的参数类型. T的用法 T表 ...

  4. AtCoder Regular Contest 093

    AtCoder Regular Contest 093 C - Traveling Plan 题意: 给定n个点,求出删去i号点时,按顺序从起点到一号点走到n号点最后回到起点所走的路程是多少. \(n ...

  5. java中set集合的常用方法

    因为Set集合也是继承Collection集合 所以这里就不讲继承Collection集合的方法 都是继承Collection集合的方法 https://www.cnblogs.com/xiaostu ...

  6. 使用Ant和YUICompressor链接合并压缩你的JS和CSS代码

    JS代码和CSS代码在上线前要压缩大家应该都是知道的了.记得之前做项目的时候,最后要交差的时候是找了个网站,将JS代码的文件一个一个地复制,粘贴,复制,粘贴. 当时就在想:TMD有没有好一点的方法,劳 ...

  7. Sqrt(X),求平方根,折半查找

    算法分析:利用折半查找,降低算法复杂度.前面求x得y次幂,也是将y/2,都是为了降低复杂度. //折半查找的思想 public class Sqrt { public int sqrt(int x) ...

  8. 使用Executor管理Thread对象详解

    java SE5的java.util.concurrent包中的执行器(Executor)是管理Thread对象的优选方法.使用Executor管理Thread对象可以简化并发编程. Executor ...

  9. scala学习手记3 - var和val

    scala中用var和val定义变量都是可以的. 用val定义的变量是不可变的,被初始化后值就固定下来,不可以再被修改(这类似于java中的final关键字):用var定义的变量是可变的,可以任意修改 ...

  10. Mongodb笔记(二) Index

    版本:mongodb3.4; Index  : 如果mongodb不能使用索引进行排序,就会将数据放入内存中进行排序,而当内存使用超过32MB时,就会报错. 在创建索引时,应确保索引的选择力,避免多余 ...