我不知道在这里想些什么......
我们有一个作为服务运行的组件。它在我的本地机器上运行得非常好,但在其他一些机器上(两台机器上的RAM都等于2GB),它会在第二天和连续几天开始生成bad_alloc异常。问题是该过程的内存使用量保持不变,大约为50Mb级别。另一个奇怪的事情是,通过跟踪消息,我们已经定义了从stringstream对象抛出的异常,该对象只会向流中插入不超过1-2 Kb的数据。如果这很重要,我们正在使用STL-Port。
现在,当您收到bad_alloc异常时,您认为这是内存泄漏。但 所有 我们的手动分配包含在智能指针中。此外,当整个过程仅使用~50Mb(内存使用量每天保持不变(并且肯定不会上升))时,我无法理解stringstream对象如何缺少内存。
我无法为您提供代码,因为项目非常大,抛出异常的部分除了创建字符串流和<<某些数据然后记录之外别无其他功能。
所以,我的问题是......当进程只使用2GB的50Mb内存时,如何发生内存泄漏/ bad_alloc?你有什么其他的猜测可能是错的?
提前谢谢,我知道这个问题很模糊,我只是有点绝望,我尽力解释这个问题。
bad_alloc
并不一定意味着没有足够的记忆。分配函数也可能因为堆已损坏而失败。您可能有一些缓冲区溢出或代码写入已删除的内存等。
你也可以使用 Valgrind的 或其中一个 Windows替换 找到泄漏/溢出。
在您的描述中,一个可能的原因是您尝试分配一些不合理的大块,因为代码中存在错误。像这样的东西;
size_t numberOfElements;//uninitialized
if( .... ) {
numberOfElements = obtain();
}
elements = new Element[numberOfElements];
现在如果 numberOfElements
如果没有初始化它可能包含一些不合理的大数字,所以你有效地尝试分配一个3GB的块,内存管理器拒绝这样做。
所以它可能不是你的程序内存不足,而是它试图分配比在最佳条件下可能允许的内存更多的内存。
只是一种预感,
但是我在过去分配数组时遇到了麻烦
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在解决方案中讨论的堆栈框架:
C ++中是否存在最大数组长度限制?
祝一切顺利,
汤姆
使用查看机器上其他进程的配置文件 Process Explorer 从sysinternals - 你会得到 bad_alloc
如果记忆很短,即使不是你造成记忆压力。
使用检查自己的内存使用情况 UMDH 获取快照并比较一段时间内的使用情况。你必须在周期的早期做到这一点,以避免炸毁工具,但如果你的过程的行为没有随着时间的推移而降低(即没有突然的病态行为),你应该及时获得有关其内存使用情况的准确信息 T
与时间 T+t
。
另一个远景:你没有说出错误发生在三个操作中的哪一个(构造, <<
或日志),但问题可能是内存碎片,而不是内存消耗。也许stringstream找不到足够长的连续内存块来容纳几个Kb。
如果是这种情况,并且如果您在第一天运行该功能(没有发生事故),那么您可以将stringstream作为静态变量并重复使用它。据我所知,stringstream在其生命周期内没有释放缓冲区空间,因此如果它在第一天建立一个大缓冲区,它将从那时开始继续使用它(为了增加安全性,你可以通过它运行一个5Kb的虚拟字符串。它是第一次构建)。
我不明白为什么一个流会抛出。你没有转储失败的进程吗?或者可能附加调试器以查看分配器尝试分配的内容?
但如果你确实超载了 operator <<
,那么也许你的代码确实有一个bug。
只是我的2(欧元)cts ......
1.碎片?
内存可能是碎片化的。
有一次,您尝试分配SIZE字节,但分配器在内存中找不到连续的SIZE字节块,然后抛出bad_alloc。
注意:这个答案是在我读到这个可能性被排除之前写的。
签名与未签名?
另一种可能性是使用已签名的值来分配大小:
char * p = new char[i] ;
如果值 i
是负数(例如-1),投入无符号积分 size_t
将使它超越内存分配器可用的内容。
由于有符号积分的使用在用户代码中非常常见,如果仅用作无效值的负值(例如,对于失败的搜索,则为-1),这是可能的。
~className(){
//delete stuff in here
}
举例来说,使用时可能会发生内存泄漏 new
在c ++中运算符而忘记使用了 delete
运营商。
或者,换句话说,当您分配一块内存并忘记释放它时。