问题描述:
使用GlobalMemoryStatus在32位(x86)上运行没有问题,但是转用64位出现问题(.net framework 4.5),获取的内存数值不正确,并且运行后报错"尝试读取或写入受保护的内存",这段32位的代码如下:
[StructLayout(LayoutKind.Sequential)]
private struct MEMORYSTATUS
{
public uint dwLength;
public uint dwMemoryLoad;
public uint ullTotalPhys;
public uint ullAvailPhys;
public uint ullTotalPageFile;
public uint ullAvailPageFile;
public uint ullTotalVirtual;
public uint ullAvailVirtual;
}
[DllImport("Kernel32.dll")]
private static extern void GlobalMemoryStatus(ref MEMORYSTATUS lpBuffer);
static void Main()
{
MEMORYSTATUS stat = new MEMORYSTATUS();
GlobalMemoryStatus(ref stat);
}
解决问题:
根据网上的描述,可能是64位数据溢出,也有可能是“对于内存超过4 GB的计算机,GlobalMemoryStatus函数可能会返回不正确的信息,报告值为-1,表明溢出。出于这个原因,应用程序应使用GlobalMemoryStatusEx函数代替。”所以考虑用GlobalMemoryStatusEx,贴上我的64位代码。可以看到有几处不同:
1. uint->ulong,64位确实需要ulong类型,不然数据返回值为0,获取过程fail;
2. 使用了GlobalMemoryStatusEx;
3. 对statEx分配了空间:statEX.dwLength = (uint)Marshal.SizeOf(statEX); 如果不加这一句,获取过程依然fail;
[StructLayout(LayoutKind.Sequential)]
private struct MEMORYSTATUS
{
public uint dwLength;
public uint dwMemoryLoad;
public ulong ullTotalPhys;
public ulong ullAvailPhys;
public ulong ullTotalPageFile;
public ulong ullAvailPageFile;
public ulong ullTotalVirtual;
public ulong ullAvailVirtual;
public ulong ullAvailExtendedVirtual;
}
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("Kernel32.dll")]
private static extern bool GlobalMemoryStatusEx(ref MEMORYSTATUSEX lpBuffer);
static void Main()
{
MEMORYSTATUSEX statEX = new MEMORYSTATUSEX();
statEX.dwLength = (uint)Marshal.SizeOf(statEX);
GlobalMemoryStatusEx(ref statEX);
}