何时会发生内存泄漏?

时间:2010-11-22 14:17:28

标签: c++ memory-leaks windows-xp

我不知道在这里想什么...

我们有一个作为服务运行的组件。它在我的本地机器上运行得非常好,但是在其他一些机器上(两台机器RAM都等于2GB),它会在第二天和连续几天开始生成bad_alloc异常。问题是该过程的内存使用量保持不变,大约为50Mb级别。另一个奇怪的事情是,通过跟踪消息,我们已经定义了从stringstream对象抛出的异常,该对象只会向流中插入不超过1-2 Kb的数据。如果重要的话,我们正在使用STL-Port。

现在,当您收到bad_alloc异常时,您认为这是内存泄漏。但是 所有 我们的手动分配被包装到智能指针中。另外,当整个过程仅使用~50Mb时,我无法理解stringstream对象如何缺少内存(内存使用量每天都保持不变(并且肯定不会上升))。

我无法为您提供代码,因为项目非常大,抛出异常的部分除了创建字符串流和<<一些数据然后记录下来。

所以,我的问题是......当进程只使用2GB的50Mb内存时,如何发生内存泄漏/ bad_alloc?你还有什么其他的猜测可能是错的?

在此先感谢,我知道这个问题很模糊,我只是有点绝望,我尽力解释这个问题。

8 个答案:

答案 0 :(得分:5)

您的描述中有一个可能的原因是,由于代码中的错误,您尝试分配一些不合理的大块。像这样的东西;

 size_t numberOfElements;//uninitialized
 if( .... ) {
    numberOfElements = obtain();
 }
 elements = new Element[numberOfElements];

现在如果numberOfElements未初始化,它可能包含一些不合理的大数字,所以你有效地尝试分配一个3GB的块,内存管理器拒绝这样做。

所以可能不是你的程序内存不足,而是它试图分配比在最佳条件下可能允许的内存更多的内存。

答案 1 :(得分:4)

bad_alloc并不一定意味着内存不足。分配函数也可能因为堆已损坏而失败。您可能有一些缓冲区溢出或代码写入已删除的内存等。

您还可以使用Valgrind或其中一个Windows replacements来查找泄漏/溢出。

答案 2 :(得分:1)

只是预感,

但是我在过去分配数组时遇到了麻烦

int array1[SIZE];  // SIZE limited by COMPILER to the size of the stack frame

当SIZE是一个很大的数字时。

解决方案是使用新运算符

进行分配
int* array2 = new int[SIZE];  // SIZE limited only by OS/Hardware

我发现这非常混乱,原因是Martin York在解决方案中讨论的堆栈帧: Is there a max array length limit in C++?

一切顺利,

汤姆

答案 3 :(得分:1)

使用来自sysinternals的Process Explorer检查机器上其他进程的配置文件 - 如果内存很短,您将获得bad_alloc,即使不是因为这会导致内存压力。

使用umdh检查您自己的内存使用情况,以获取快照并比较一段时间内的使用情况。你必须在周期的早期做到这一点,以避免炸毁工具,但如果你的过程的行为没有随着时间的推移而降低(即没有突然的病态行为),你应该及时获得有关其内存使用情况的准确信息{{1对时间T

答案 4 :(得分:0)

我无法理解为什么流会抛出。你没有转储失败的进程吗?或者可能附加调试器以查看分配器尝试分配的内容?

但如果你确实超载了operator <<,那么你的代码可能确实存在错误。

只是我的2(欧元)cts ......

1。碎片?

内存可能会碎片化。

有一次,你尝试分配SIZE字节,但是分配器在内存中找不到连续的SIZE字节块,然后抛出bad_alloc。

注意:这个答案是在我读到这个可能性被排除之前写的。

2。签名与未签名?

另一种可能性是使用签名值来分配大小:

char * p = new char[i] ;

如果i的值为负(例如-1),则转换为无符号整数size_t将使其超出内存分配器可用的范围。

由于在用户代码中使用有符号积分非常常见,如果仅用作无效值的负值(例如,对于失败的搜索,则为-1),这是可能的。

答案 5 :(得分:0)

另一个长镜头:你没有说出错误发生在三个操作中的哪一个(构造,<<或log),但问题可能是内存碎片,而不是内存消耗。也许stringstream找不到足够长的连续内存块来保存几个Kb。

如果是这种情况,并且如果您在第一天运行该功能(没有发生事故),那么您可以将stringstream作为静态变量并重复使用它。据我所知,stringstream在其生命周期内没有释放缓冲区空间,因此如果它在第一天建立一个大缓冲区,它将从那时开始继续使用它(为了增加安全性,你可以通过它运行一个5Kb的虚拟字符串。它是第一次构建的。)

答案 6 :(得分:0)

 ~className(){

 //delete stuff in here

}

答案 7 :(得分:-1)

举例来说,当您在c ++中使用new运算符并忘记使用delete运算符时,可能会发生内存泄漏。

或者,换句话说,当你分配一块内存并忘记解除分配时。