2

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

考虑以下测试:

// 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 设备上,ReadFileWriteFile将失败并出现错误 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
4

3 回答 3

2

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

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

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

于 2009-05-22T23:11:49.827 回答
2

不,这是不可能的。

于 2009-05-25T16:16:21.407 回答
1

喔好吧。在那种情况下,您是否听说过大内存区域,我认为这是 Microsoft 针对您的问题的解决方法/解决方案。

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

这里有一个很好的讨论它是如何工作的:http:
//msdn.microsoft.com/en-us/library/ms836325.aspx

我自己在以前的产品上使用过它,它对我有用。

于 2009-05-24T19:35:59.890 回答