我一直在使用内存空间profiler来获取内存的图片.我写了一个1行程序,其中包含cin>> VAR;并拍摄了记忆:
alt text http://img22.imageshack.us/img22/6808/memoryk.gif
顶部圆弧 – 绿色表示空白处,黄色分配,红色表示.我的问题是右边分配的内存是什么?是主线程的堆栈吗?这个内存不会被释放,它分割了我需要的连续内存.在这个简单的1线程序中,分割没有那么糟糕.我的实际程序有更多的东西分配在地址空间的中间,我不知道它在哪里.我还没有分配那个内存.
>我该如何解决这个问题?我正在考虑切换到像nedmalloc或dlmalloc这样的东西.然而,这只适用于我自己明确分配的对象,而图中所示的分割不会消失?还是有办法用另一个内存管理器来替换CRT分配?
>说到对象,有没有为nedmalloc包装c,所以我可以使用新的和删除来分配对象?
谢谢.
解决方法
通常,地址空间中固定点处的薄片是由其首选地址加载的链接dll引起的.在地址空间中加载的数据往往是Microsoft操作系统dll.如果这些操作系统都可以在其首选地址中加载,那么操作系统的效率更高,因为dll的只读部分都可以在进程之间共享.
你可以看到的切片是没有什么可担心的,它几乎没有任何东西从您的地址空间中删除.正如你所注意到的,但是,有些DLL在地址空间的其他点加载. IIRC shlwapi.dll是一个特别糟糕的例子,加载大约0x2000000(再次是IIRC),它经常将大部分可用的地址空间分成两个较小的块.这样做的问题是,一旦DLL被加载,你可以做任何事情来移动这个分配空间.
如果您链接到DLL(直接或通过另一个DLL),没有什么可以做的.如果您使用LoadLibrary,您可以在释放该保留的内存之前,先获取首选地址,并强制将其重新定位到地址空间更多的地方.这并不总是奏效.
在引擎盖下,地址空间监视器使用VirtualQueryEx来检查进程的地址空间,但是还有另一个调用来自psapi库,其他工具使用(例如Process Explorer)可以显示哪些文件(包括DLL)映射到地址空间.
如您所见,在2GB用户地址空间中,可能会很容易耗尽空间.从根本上说,你最好防止内存碎片简单地不需要任何大的连续的内存块.虽然难以适应,但是设计您的应用程序可以使用“中等大小”的块通常使地址空间的使用更加有效.
类似地,您可以使用分页策略,可能使用内存映射文件或Address Windowing Extensions.