`
风吹过PP好冷
  • 浏览: 38056 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

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

阅读更多

实际应用中一个程序在长时间运行后内存占用较高时发生崩溃,从dump信息中,发现GetAdaptersInfo函数返回了一个奇怪的错误码998(ERROR_NOACCESS),百度搜索不到相关的信息。MSDNGetAdaptersInfo函数的错误码正常情况下只有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报告及建议网站上找到了一篇文章,<GetAdaptersAddresses API incorrectly returns no adapters for a process with high memory consumption>, http://connect.microsoft.com/VisualStudio/feedback/details/665383/getadaptersaddresses-api-incorrectly-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的进程内存占用,同样佐证了我们的猜测。

分享到:
评论

相关推荐

    获取本机网卡的物理地址程序(VB6.0源代码编写)' API函数声明

    注意:由于VB6中没有`LongPtr`类型来处理不同平台的指针,因此在64位系统上可能需要修改`GetAdaptersInfo`函数的声明和`pAdapterInfo`变量的类型。此外,实际使用时应处理可能出现的错误情况,例如分配内存失败或API...

    取本机mac地址.rar

    在IT领域,MAC(Media Access Control)地址是一个用于标识网络硬件设备的独特地址,通常用于局域网中的数据传输。在Delphi编程环境下,获取本地计算机的MAC地址是常见的需求,尤其是在进行网络通信或者设备识别时。...

    vb读网卡的实例,读过网卡号码

    在VB(Visual Basic)编程环境中,获取网卡(网络适配器)的MAC地址是一个常见的需求,这在很多网络相关的应用程序中是必要的。MAC地址,全称Media Access Control Address,是一个用于唯一标识网络设备的物理地址。...

    读取网卡物理地址

    在计算机网络中,网卡物理地址,也称为MAC(Media Access Control)地址,是一个独一无二的硬件标识符,每个网络适配器(网卡)都有一个。这个地址在局域网通信中扮演着至关重要的角色,因为它是数据帧在网络中定向...

    利用C++Builder获取网卡Mac地址

    Mac地址,全称Media Access Control Address,是一个48位的二进制数,通常以六组两位的十六进制数表示,如"00:14:22:01:23:45"。它是网络设备连接到局域网(LAN)时的硬件地址,用于数据帧的物理寻址。 在C++...

    MAC地址获得.rar_delphi mac_mac_mac address_获得Mac地址

    在IT领域,MAC(Media Access Control)地址是一个用于标识网络硬件设备的独特地址,通常与网卡(NIC,Network Interface Card)绑定。MAC地址是物理地址,由48位二进制组成,通常以12个十六进制数字表示,如00:11:...

    vc++编程之获取网卡地址

    此外,如果你的程序需要在多线程环境下运行,可能还需要考虑同步问题。 总的来说,获取网卡地址是通过调用Windows API来实现的,这需要对VC++和Windows系统编程有深入的理解。在开发过程中,确保正确地使用和管理...

    获取网卡的MAC地址

    `GetAdaptersInfo`函数在`Iphlpapi.h`头文件中定义,它返回一个`IP_ADAPTER_INFO`结构体数组,包含了所有网络适配器的信息。而`GetAdaptersAddresses`则提供了更灵活的方式,可以从`IpHlpApi.h`中找到,它可以获取更...

    VB 查看MAC地址

    在VB(Visual Basic)编程环境中,查看MAC地址是一项常见的任务,尤其在系统信息获取或网络通信相关的应用中。MAC(Media Access Control)地址是物理网络接口控制器的唯一标识,它是一个48位的数字,通常以冒号或破...

    网卡MAC读取(VC++)实现

    需要注意的是,`GetAdaptersInfo()`函数返回的信息中,MAC地址是以无符号字节数组的形式存储的,因此在输出时需要转换为通常的冒号分隔格式。 此外,由于涉及到Windows API,所以这个程序只适用于Windows操作系统。...

    取得本机所有网卡(网络连接)的MAC地址.rar

    在IT领域,获取本机所有网卡(网络连接)的MAC地址是一项常见的需求,尤其是在系统管理和网络编程中。本文将详细讲解如何通过VB(Visual Basic)实现这一功能,并结合提供的"ModGetPhysicalAddress.bas"模块文件进行...

    GetIPAddress获取网卡及IP地址

    IP(Internet Protocol)地址是互联网上的设备在网络层的逻辑地址,IPv4通常为32位,IPv6则为128位,以点分十进制或冒号十六进制表示。 在Delphi中,我们可以使用WinAPI函数来获取这些信息。对于MAC地址,可以调用`...

    VC++得到本台计算机的MAC地址

    在IT领域,尤其是在软件开发中,获取计算机的MAC(Media Access Control)地址是一项常见的任务,特别是在需要进行身份验证或网络通信的场景下。MAC地址是一个硬件级别的标识符,用于唯一地识别网络上的设备。在VC++...

    读取pc上网卡id的程序

    在IT领域,尤其是在系统编程和网络通信中,识别和管理硬件设备是至关重要的。这个“读取PC上网卡ID的程序”就是一个典型的示例,它使用VC++(Visual C++)这一强大的C++开发环境来获取计算机上的网络接口控制器(NIC...

    获取MAC地址.7z

    在Windows系统下,可以使用`iphlpapi.dll`库中的`GetAdaptersInfo`或`GetAdaptersAddresses`函数来获取网络接口卡(NICs)的信息,其中包括MAC地址。 以下是一个基本的Delphi代码示例,演示了如何使用`...

    DELPHI 2010 获取MAC地址

    在编程领域,尤其是在使用Delphi 2010这样的集成开发环境时,有时我们需要获取计算机的物理硬件信息,其中就包括MAC(Media Access Control)地址。MAC地址是网络设备(如网卡)的唯一标识符,它在局域网通信中起到...

    vc6.0获取网卡地址

    在VC6.0环境下,开发一个程序来获取并显示计算机上的网卡(NIC)MAC地址是一项常见的任务。本文将详细讲解如何使用C++在Visual C++ 6.0中实现这个功能,以及涉及到的关键知识点。 首先,我们需要了解MAC(Media ...

    获取计算机MAC地址和硬盘序列号的C++代码

    获取MAC地址通常涉及到操作系统底层的网络编程,对于Windows系统,可以使用WinPCap库或Windows API函数`GetAdaptersInfo`。以下是一个简单的示例: ```cpp #include #include #include #pragma comment(lib, ...

    获取电脑MAC地址,附源代码与exe执行文件

    在IT领域,MAC(Media Access Control)地址是一个用于标识网络硬件设备的独特地址,通常用于局域网中的数据传输。在Windows操作系统中,获取电脑的MAC地址对于系统管理和网络配置是必要的。本文将深入探讨如何使用...

Global site tag (gtag.js) - Google Analytics