2011-11-18 156 views
3

我有一个非常简单的问题,我似乎被困在发生的事情。请看下面的代码:CArray没有取消分配内存

CArray<double, double&> arr; 
arr.SetSize(50000); 

for(int i =0; i< 50000; i++) 
{ 
    arr[i] = (i+2)*3.14f; 
} 

arr.RemoveAll(); 

我会假设,RemoveAll()后,内存将被释放,但现在看来似乎没有发生。要检查内存占用情况,请打开Taskmanager并观察exe的内存。它在arr.SetSize()呼叫上增加,但即使此arr超出范围,它也不会减少。有人可以对此进行阐述吗?

回答

7

第一件事:

任务管理器=内存分析器

操作系统(或者更具体地说是C运行时系统)肯定会缓存一些你分配的内存。

注意,操作系统通常不是哑巴 - 如果它是不是正在使用的应用程序的内存和操作系统需要更多的内存来满足其他一些程序的内存需求,这将相应地分配。但是,如果情况并非如此(大多数情况下不是这样),那么当应用程序成为获胜策略时,应该重复使用它。

由于这些类型的优化,你真的不能使用任务管理器获取应用程序的内存使用情况的精确视图。

第二件事:

像所有非傻动态数组类,CArray当你删除所有的情况下,你需要再次使用的内存缓冲区中的元素不会释放内存甚至支持的阵列。如果删除底层内存缓冲区只会浪费更多的处理器周期来重新分配另一个缓冲区来处理可能在CArray::RemoveAll()之后发生的下一个CArray::Append()调用,那么这会浪费处理器周期。

如果你真的想摆脱多余的空间,使用CArray::FreeExtra()。请注意,该函数可能涉及分配一个新的缓冲区并将这些元素复制到新的缓冲区,然后删除旧的缓冲区。

+0

我试过FreeExtra,但它仍然无法正常工作。我知道任务管理器不是内存分析器,但这是最容易获得的东西。还有其他建议吗? – Aamir

+0

@In Silico,为什么FreeExtra需要分配一个新的缓冲区来减小大小?当然,如果它使用realloc来缩小所使用的内存量,最终会产生碎片堆,那么可以避免额外堆空间的内存开销以及复制和调用ctors和dtors的时间开销。 –

+0

@Shane MacLaughlin:这是一种可行的方法。但是,文档没有具体说明也没有做出任何保证,让它像那样工作(我已经重写了这句话)。它不是普遍的;例如'std :: vector'几乎肯定会分配一个新缓冲区并删除旧缓冲区,因为分配器接口没有'realloc()'能力。 –

1

你需要调用FreeExtra您的removeAll后获取内存了。我猜这是为了避免堆碎片。

2

正如别人所说,removeall过不会释放CARRAY分配的内存,你需要调用CARRAY :: FreeExtra。

你说在CArray的析构函数之后内存不会下降。 CArray :: SetSize从堆中分配内存,CArray的析构函数释放它。但是,这并不意味着堆内存将回馈给操作系统。

当您使用MFC我建议不时在调试器中启动程序。 MFC调试应用程序在MFC清理过程中打印出他们的内存泄漏(基于新的)。