Windows Mobile上连续的VirtualAlloc行为

时间:2009-05-17 15:23:41

标签: c++ windows-mobile memory-management windows-ce virtualalloc

我一直在优化Windows Mobile应用程序的内存性能,并且在 VirtualAlloc on Win32Windows CE之间的行为方面遇到了一些差异。

考虑以下测试:

// Allocate 64k of memory
BYTE *a = (BYTE*)VirtualAlloc(0,       65536,
                              MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
// Allocate a second contiguous 64k of memory
BYTE *b = (BYTE*)VirtualAlloc(a+65536, 65536,
                              MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);

BYTE *c = a + 65528; // Set a pointer near the end of the first allocation
BOOL valid1 = !IsBadWritePtr(c, 8); // Expect TRUE
BOOL valid2 = !IsBadWritePtr(c+8, 4088); // Expect TRUE
BOOL valid3 = !IsBadWritePtr(c, 4096); // TRUE on Win32, FALSE on WinCE

代码“分配”从“c”开始的4096个数据。在Win32上这是有效的。我在 VirtualAlloc 文档中找不到提及它是合法的还是巧合的,但是我通过谷歌找到的许多代码都会出现这种行为。

在Windows CE 5.0 / 5.2上如果我在“c”处使用内存块,99%的情况下没有问题,但在某些(并非所有)Windows Mobile 6设备上, ReadFile &安培; WriteFile 将失败,错误87(参数不正确。)。我假设 ReadFile 正在调用 IsBadWritePtr 或类似的,并因此而返回false。如果我执行两个 ReadFile 调用,那么一切正常。 (当然可能还会有其他API调用失败。)

我正在寻找一种方法来扩展 VirtualAlloc 返回的内存,以便我可以完成上述工作。在Windows CE上保留大量内存是有问题的,因为每个进程只获得32MB并且由于其他项目被加载,因此无法在不引起其他问题的情况下保留大的内存区域。 (可以在共享区域中保留更多的内存,但这也存在其他问题。)

有没有办法让 VirtualAlloc 扩大或组合区域而不预先保留它?

我怀疑在以下示例中可能存在问题:

HANDLE hHeap1 = HeapCreate(0, 0, 0); // Heap defaults to 192k
BYTE * a1 = (BYTE*)HeapAlloc(hHeap1, 0, 64000); // +96 bytes from start of heap
BYTE * b1 = (BYTE*)HeapAlloc(hHeap1, 0, 64000); // +16 bytes from end of a1
BYTE * c1 = (BYTE*)HeapAlloc(hHeap1, 0, 64000); // +16 bytes from end of b1
BYTE * d1 = (BYTE*)HeapAlloc(hHeap1, 0, 64000); // +4528 bytes from end of c1

HANDLE hHeap2 = HeapCreate(0, 4*1024*1024, 4*1024*1024); // 4MB Heap
BYTE * a2 = (BYTE*)HeapAlloc(hHeap2, 0, 64000); // +96 bytes from start of heap
BYTE * b2 = (BYTE*)HeapAlloc(hHeap2, 0, 64000); // +16 bytes from end of a2
BYTE * c2 = (BYTE*)HeapAlloc(hHeap2, 0, 64000); // +16 bytes from end of b2
BYTE * d2 = (BYTE*)HeapAlloc(hHeap2, 0, 64000); // +16 bytes from end of c2

3 个答案:

答案 0 :(得分:2)

我不相信IsBadWritePtr,看到这个: http://support.microsoft.com/kb/960154 我认为这样做会尝试写入内存,并查看它是否获得硬件异常。它处理异常然后返回true或false。但是,我听说有些硬件只会在尝试写入一个页面时引发一次异常,或类似的东西。

如果没有MEM_COMMIT,您是否无法使用VirtualAlloc,因此您只需保留虚拟内存地址。然后,当您确实想要使用内存时,再次调用VirtualAlloc进行提交。由于您已经保留了页面,因此您应该能够连续提交它们。

你说你想要在没有预先保留的情况下这样做。但是,预先保留有什么问题。保留实际上不使用任何物理内存,它保留一系列虚拟地址,它只在您提交页面时使用物理内存。

答案 1 :(得分:2)

不,这是不可能的。

答案 2 :(得分:1)

啊,好的。在那种情况下你听说过大内存区域,我认为这是微软的解决方法/解决你的问题。

基本上,如果VirtualAlloc超过2 meg,它会进入虚拟内存的大内存区域,这会让你超过32mb的限制。

关于这一切是如何运作的,有很好的讨论:
http://msdn.microsoft.com/en-us/library/ms836325.aspx

我自己在以前的产品上使用它,它为我做了诀窍。