实际应用中一个程序在长时间运行后内存占用较高时发生崩溃,从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报告及建议网站上找到了一篇文章,<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的进程内存占用,同样佐证了我们的猜测。
分享到:
相关推荐
hook_GetAdaptersInfo
39422_GetAdaptersInfo1 取得系統資源
有位老师告诉我说网上的 取网卡的名字都是错的 网上大部分用的是 PacketGetAdapterNames 取所有网卡名字的字符串 而 老师告诉我 正确的应该用 GetAdaptersInfo 来取 其网卡信息 然后再 从相关结构体中取出 这个问题...
获取客户端IP函数详细做法, Function getIP() Dim strIPAddr If Request.ServerVariables("HTTP_X_FORWARDED_FOR") = "" OR InStr(Request.ServerVariables("HTTP_X_FORWARDED_FOR"), "unknown") >0 Then ...
使用windows sdk提供的API函数GetAdaptersInfo获得本机所有网卡的网卡名、网卡描述、网卡MAC地址、网卡IP、网卡类型等信息,并用IP_ADAPTER_INFO结构体存储,使用GetIfEntry获取网卡的状态,可有效判断出网卡通讯...
GetAdaptersInfo 和 GetAdaptersAddresses 都能获取网络相关信息,如网卡名称、MAC 地址、IP、DNS、网关等信息,但是两个函数感觉都有一些问题,GetAdaptersInfo 获取不到 IPV6 地址信息,使用起来较为简单,...
功能的实现都非常简单,有五种函数可以直接调用: 1.用于获取本地网络适配器信息的函数: DWORD GetAdaptersInfo( PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen ); 2.用于获取本地主机名、域名和DNS服务器...
pb使用函数GetAdaptersInfo 这个资源,是我自己写的代码,我违反了什么规定?
hook_钩子程序-delphihook_钩子程序-delphihook_钩子程序-delphi
实战DeviceIoControl教你如何运用实战DeviceIoControl函数读取硬件信息
利用GetAdaptersInfo函数获取本地所有IP地址的小软件源代码。
易语言获得网卡信息类 系统结构:获取网络信息_DOS管道,获取网络信息_API,判断控制,操作网卡,设置IP地址,前缀补零,过滤函数,GetAdaptersInfo,Len_iai,Len_ias,取变量地址_字节集,CopyMemory_iai,Copy
安装FME时,如果电脑没有网卡,Error 管道正在被关闭,from GetAdaptersInfo,怎么办呢?
调用GetAdaptersInfo获取网卡信息并通过WIFIAPI获取当前无线网卡状态和SSID信息。
本文介绍如何使用命令行工具,获取运行 Microsoft Windows XP Service Pack 2 (SP2)、Windows Server 2003、Windows Vista (目前处于 beta 测试阶段)或 Windows Server“Longhorn”(目前处于 beta 测试阶段)的...
易语言取网卡信息源码,取网卡信息,子程序1,GetAdaptersInfo,Len_iai,Len_ias,取变量地址_字节集,CopyMemory_iai,CopyMemory_ias
hook deviceiocontrol api 实现随机序列号可修改代码指定序列号
WinCE下设置网卡参数,不需要重启 GetAdaptersInfo DeviceIoControl( hNdis, IOCTL_NDIS_REBIND_ADAPTER, Names, _tcslen( Names) + sizeof( TCHAR ),
VC++源码 一个使用detours来HookAPI的简单例子 ...GetAdaptersInfo获取MAC Hook这两个API改变获取的硬盘串号和MAC地址 HDHook工程 生成dll GetHDDSN工程 载入生成的dll 获取硬盘串号和MAC地址 需要自行安装detours