我不知道在这里想什么...
我们有一个作为服务运行的组件。它在我的本地机器上运行得非常好,但是在其他一些机器上(两台机器RAM都等于2GB),它会在第二天和连续几天开始生成bad_alloc异常。问题是该过程的内存使用量保持不变,大约为50Mb级别。另一个奇怪的事情是,通过跟踪消息,我们已经定义了从stringstream对象抛出的异常,该对象只会向流中插入不超过1-2 Kb的数据。如果重要的话,我们正在使用STL-Port。
现在,当您收到bad_alloc异常时,您认为这是内存泄漏。但是 所有 我们的手动分配被包装到智能指针中。另外,当整个过程仅使用~50Mb时,我无法理解stringstream对象如何缺少内存(内存使用量每天都保持不变(并且肯定不会上升))。
我无法为您提供代码,因为项目非常大,抛出异常的部分除了创建字符串流和<<一些数据然后记录下来。
所以,我的问题是......当进程只使用2GB的50Mb内存时,如何发生内存泄漏/ bad_alloc?你还有什么其他的猜测可能是错的?
在此先感谢,我知道这个问题很模糊,我只是有点绝望,我尽力解释这个问题。
答案 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 ......
内存可能会碎片化。
有一次,你尝试分配SIZE字节,但是分配器在内存中找不到连续的SIZE字节块,然后抛出bad_alloc。
注意:这个答案是在我读到这个可能性被排除之前写的。
另一种可能性是使用签名值来分配大小:
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
运算符时,可能会发生内存泄漏。
或者,换句话说,当你分配一块内存并忘记解除分配时。