代码之家  ›  专栏  ›  技术社区  ›  Armen Tsirunyan

什么时候会发生内存泄漏?

  •  11
  • Armen Tsirunyan  · 技术社区  · 14 年前

    我不知道该怎么想。。。

    我们有一个作为服务运行的组件。它在我的本地计算机上运行得非常好,但在另一台计算机上(两台计算机的RAM都等于2GB),它在第二天和连续几天开始生成坏的分配异常。问题是,进程的内存使用在接近50MB的水平上保持不变。另一个奇怪的事情是,通过跟踪消息,我们将异常本地化为从stringstream对象抛出,该对象只向流中插入不超过1-2kb的数据。如果重要的话,我们用的是STL端口。

    现在,当您得到一个坏的分配异常时,您认为这是内存泄漏。但是 全部的 我们的手动分配被包装成一个智能指针。另外,当整个过程只使用~50MB(内存使用量保持不变(并且肯定不会上升))时,我不能理解StrueSnkes对象缺少内存。

    我无法向您提供代码,因为项目非常大,抛出异常的部分实际上只会创建一个stringstream和一些数据,然后将其记录下来。

    所以,我的问题是。。。当进程在2GB中仅使用50Mb内存时,如何发生内存泄漏/内存分配错误?你对可能出了什么问题还有什么疯狂的猜测吗?

    提前谢谢,我知道这个问题很模糊等等,我只是有点绝望,我尽力解释这个问题。

    8 回复  |  直到 14 年前
        1
  •  4
  •   Community CDub    7 年前

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

    你也可以用 Valgrind 或者它的一个 Windows replacements 查找泄漏/溢出。

        2
  •  5
  •   sharptooth    14 年前

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

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

    现在如果 numberOfElements 如果不进行初始化,它可能包含一些不合理的大数字,因此您可以有效地尝试分配一个内存管理器拒绝执行的块,例如3GB。

    所以,这可能不是因为你的程序内存不足,而是因为它试图分配更多的内存,即使是在最好的条件下也不可能。

        3
  •  1
  •   Community CDub    7 年前

    只是一种预感,

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

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

    当尺寸很大时。

    解决方案是用新的运算符分配

    int* array2 = new int[SIZE];  // SIZE limited only by OS/Hardware
    

    我发现这非常令人困惑,原因是Martin York的解决方案中讨论的堆栈框架: Is there a max array length limit in C++?

    一切顺利,

    汤姆

        4
  •  1
  •   Steve Townsend    14 年前

    使用检查机器上其他进程的配置文件 Process Explorer 从sysinternals-您将得到 bad_alloc 如果记忆不足,即使不是你造成了记忆压力。

    使用检查自己的内存使用情况 umdh 获取快照并随时间比较使用情况配置文件。您必须在周期的早期执行此操作,以避免炸毁工具,但是如果您的进程的行为没有随着时间的推移而降低(即没有突然的病理行为),那么您应该及时获得有关其内存使用的准确信息 T vs时间 T+t .

        5
  •  0
  •   Beta    14 年前

    另一个长远目标是:你不会说在三个操作中哪一个出错(构造, << 但问题可能是内存碎片,而不是内存消耗。可能stringstream找不到足够长的连续内存块来容纳几Kb。

    如果是这样的话,并且如果您在第一天就使用了该函数(没有意外),那么您可以将stringstream设置为一个静态变量并重用它。据我所知,stringstream在其生命周期中不会释放它的缓冲区空间,因此如果它在第一天建立了一个大缓冲区,它将从那时起继续拥有它(为了增加安全性,您可以在它第一次构造时通过它运行一个5Kb的伪字符串)。

        6
  •  0
  •   paercebal    14 年前

    我不明白为什么一条小溪会抛掷。你没有一堆失败的过程吗?或者可能附加一个调试器来查看分配器试图分配什么?

    但如果你真的超负荷 operator << ,则可能您的代码确实有错误。

    只有我的两个(欧元)cts。。。

    一。分裂?

    内存可能是碎片。

    有一次,您尝试分配大小字节,但分配器在内存中找不到连续的大小字节块,然后抛出一个错误的分配。

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

    2。签名与未签名?

    另一种可能是对要分配的大小使用带符号的值:

    char * p = new char[i] ;
    

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

    由于符号积分在用户代码中很常见,如果仅用作无效值的负值(例如,-1表示搜索失败),则这是一种可能性。

        7
  •  0
  •   Alex Spencer    12 年前
     ~className(){
    
     //delete stuff in here
    
    }
    
        8
  •  -1
  •   Alex Spencer    10 年前

    举例来说,当您使用 new 运算符,忘记使用 delete 接线员。

    或者,换句话说,当你分配一个内存块而忘记释放它时。