我一直在使用一个内存空间分析器来获取内存的情况。我写了一个包含cin >> var;的1行程序,并对内存进行了截图:
![alt text](https://img22.imageshack.us/img22/6808/memoryk.gif)
2. 我该如何解决这个问题?我正在考虑切换到像nedmalloc或dlmalloc这样的东西。然而,这只适用于我明确分配的对象,而在图片中显示的分裂并不会消失?还是有一种方法可以用另一个内存管理器替换CRT分配?
3. 说到对象,是否有nedmalloc的c++包装器,以便我可以使用new和delete来分配对象?
首先,感谢您使用我的工具。希望您觉得它有用,欢迎提交功能请求或贡献。
通常,在地址空间的固定点处进行的薄切片是由链接的dll在它们的首选地址处加载引起的。高处加载在地址空间中的dll倾向于是Microsoft操作系统dll。如果所有这些都可以在它们的首选地址处加载,那么操作系统的效率会更高,因为这样dll的只读部分可以在进程之间共享。
您看到的那个切片没什么好担心的,它几乎没有占用您的地址空间。但是,正如您所指出的,还有一些dll加载在地址空间的其他位置。我记得 shlwapi.dll 是一个特别糟糕的例子,加载在大约0x2000000(再次记得)的位置上,这经常将可用地址空间的大部分划分为两个较小的部分。问题在于,一旦加载了DLL,您无法对此分配的空间进行移动。
如果您直接或通过另一个DLL链接到该DLL,则无法做任何事情。如果使用 LoadLibrary ,则可以获取巧妙并保留其首选地址,将其强制重新定位-通常是在地址空间中更好的位置-然后释放该保留内存。不过这并不总是有效。
在幕后,地址空间监视器使用 VirtualQueryEx 检查进程的地址空间,但有另一个来自psapi库的调用,其他工具也会使用它(例如 Process Explorer ),可以向您展示将哪些文件(包括DLL)映射到地址空间的哪些部分。
正如您发现的那样,在2GB用户地址空间中很容易用完空间。从根本上说,对内存碎片化的最佳防御措施就是不需要任何大块连续的内存。虽然难以进行反向安装,但将应用程序设计为使用“中等大小”的块通常可以更有效地使用地址空间。
类似地,您可以使用分页策略,可能使用内存映射文件或地址窗口扩展(AWE)。
0:004> !vadump
BaseAddress: 0000000000000000
RegionSize: 0000000000010000
State: 00010000 MEM_FREE
Protect: 00000001 PAGE_NOACCESS
BaseAddress: 0000000000010000
RegionSize: 0000000000010000
State: 00001000 MEM_COMMIT
Protect: 00000004 PAGE_READWRITE
Type: 00040000 MEM_MAPPED
BaseAddress: 0000000000020000
RegionSize: 0000000000003000
State: 00001000 MEM_COMMIT
Protect: 00000002 PAGE_READONLY
Type: 00040000 MEM_MAPPED
希望这能解释清楚事情。Windbg是一个很棒的工具,有许多扩展可以帮助你找到内存使用的位置。
如果你只关心堆,那就看看!heap。
可能是可执行文件的问题吗?它必须加载到某个地址空间中....
至于第二点,覆盖全局 new 和 delete 函数非常容易...只需定义它们即可。