无法追踪巨大内存使用的来源

时间:2011-07-15 12:57:44

标签: c++ memory-management

我一直试图追踪内存问题几天 - 我的程序使用大约3GB的内存,当它应该使用大约200MB-300MB。 Valgrind实际上报告它在峰值时使用了大约300MB,并且没有报告任何内存泄漏。

程序读取输入文件,并将每个唯一的单词存储在该文件中。它是多线程的,我一直使用4个线程运行它。我的主要数据来源是:

  • wchar_t的恒定大小数组(总共4MB)
  • 在单词和关联值列表之间映射。这随着输入的大小而增长。如果输入文件中有1,000,000个唯一单词,则树中将有1,000,000个条目。

我正在进行大量的分配和解除分配(使用new和delete) - 每个唯一的字至少有两个。是否有可能因为某些原因而没有重用内存,导致程序继续获取越来越多的内存?随着它继续运行,它一直在抓住更多。

总的来说,关于我应该从哪里开始的任何想法?

编辑1(根据格雷厄姆的建议): 我将尝试的一条路径是最小化分配。我将使用每个线程一个字符串(如果一个单词比这个字符串长,它可能会偶尔增长),但如果我正确记住我的代码,这将消除大量的新/删除调用。如果一切顺利,我将留下:一次性分配输入缓冲区,一次性分配每个线程的字符串(带有一些reallocs),每个映射条目两个alloc(一个用于键,一个用于值)。

谢谢!

3 个答案:

答案 0 :(得分:7)

可能是堆碎片。因为您正在分配和释放如此大量的小块,所以很可能存在大量小的空闲块,这些块太小而不能被后续分配重用。由于这些块被有效地浪费了,因此该过程必须继续从系统中获取越来越多的内存以兑现新的分配。

您可以通过首先使用string::reserve()在每个字符串中保留足够大的默认容量来缓解效果,然后在完成它们时清除字符串为空(而不是删除)。然后,保留一个空字符串列表以供重用,而不是一直分配新字符串。

编辑:上述建议假定分配的对象为std::string s。如果它们不存在,那么您可能仍然可以应用保留旧空对象以便重复使用的一般技术。

答案 1 :(得分:0)

应该将程序释放的内存返回到可以再次分配的堆中。

然而,这并不意味着它被释放回操作系统。通常,应用程序将继续“拥有”已分配和释放的内存。

这是一个Windows应用程序吗?你是如何分配和释放内存的?你如何确定应用程序使用了多少内存?

答案 2 :(得分:0)

如果可以,您应该尝试将资源分配包装到类中。在构造函数中调用new,并在析构函数中删除。尝试并利用范围,以便更自动地完成内存管理。

http://en.wikipedia.org/wiki/RAII