admin管理员组

文章数量:1531765



有多种方法来定义“内存泄漏”。特别地,在程序员中通常使用的“内存泄漏”的两个主要定义。

 
“内存泄漏”的第一个常用定义是“内存已分配,并且在程序终止之前不会被释放。然而,许多程序员(正确地)认为,符合该定义的某些类型的内存泄漏实际上不会引起任何问题,因此不应该被认为是真正的“内存泄漏”。

 
“内存泄漏”的一个可以更严格(更有用的)定义是“内存被分配,并且随后不能被释放,因为程序不再具有任何指向所分配的内存块的指针。换句话说,你不能释放你不再有任何指针的内存。因此,这样的存储器是“存储器泄漏”。 Valgrind使用这个更严格的术语“内存泄漏”的定义。这是可能引起显着堆损耗的泄漏类型,特别是对于长寿命过程。

 
Valgrind的泄漏报告中的“still reachable”类别指的是仅适合“内存泄漏”的第一个定义的分配。这些块没有被释放,但是它们可以被释放(如果程序员想要的话),因为程序仍然在跟踪那些存储器块的指针。

 
一般来说,没有必要担心“still reachable”块。他们不会造成真正的内存泄漏可能导致的问题。例如,通常没有从“still reachable”块的堆耗尽的可能性。这是因为这些块通常是一次性分配,其引用在整个过程的生存期内保持。虽然可以通过并确保您的程序释放所有分配的内存,但通常没有实际的好处,因为操作系统将在进程终止后回收所有进程的内存。与真正的内存泄漏对比,如果不固定,如果运行时间足够长,可能会导致进程运行内存不足,或者只是导致进程消耗比必要的更多的内存。

 
可能唯一确保所有分配具有匹配的“释放”的时间是,如果你的泄漏检测工具不能告诉哪些块是“still reachable”(但Valgrind可以这样做),或者如果你的操作系统不收回所有终止进程的内存(Valgrind已经移植到的所有平台)。


1.   "只要分配了内存没有释放,就会导致内存泄漏"   --   这是我以前的理解,   是片面的.   

分配了的内存,如果它的指针没有丢失,就不算是泄漏.   一般说来,为static指针变量或全局的指针变量(它们的生存期是全局的)进行内存分配,如果没有释放它,虽然这也是"not-freed   blocks",但是它是"reachable"的.现代的OS会得到这些指针并去释放它.   

  下面是两个例子:   
    
  1)   使用全局指针或静态指针:   
  int   main()   
  {   
          static   int   *pi;     //   use   static   pointer:   not   a   real   memory   leak!!!   
          pi   =   new   int;   
          return   0;   
  }   
    
  使用valgrind检查:     
  valgrind   --leak-check=yes   --show-reachable=yes   -q   ./memtest   
    
  ==13764==   searching   for   pointers   to   1   not-freed   blocks.   
  ==13764==   checked   4488448   bytes.   
  ==13764==   
  ==13764==   4   bytes   in   1   blocks   are   still   reachable   in   loss   record   1   of   1   
  ==13764==         at   0xB74D27AB:   __builtin_new   (vg_replace_malloc.c:172)   
  ==13764==         by   0xB74D2802:   operator   new(unsigned)   (vg_replace_malloc.c:185)   
  ==13764==         by   0x8048491:   main   (in   /home/prog/valgrind/memtest)   
  ==13764==         by   0xB71C4BA6:   __libc_start_main   (in   /lib/libc-2.3.2.so)   
  ==13764==   
  ==13764==   LEAK   SUMMARY:   
  ==13764==         definitely   lost:   0   bytes   in   0   blocks.   
  ==13764==         possibly   lost:       0   bytes   in   0   blocks.   
  ==13764==         still   reachable:   4   bytes   in   1   blocks.   
  ==13764==                   suppressed:   0   bytes   in   0   blocks.   
  ==13764==   
  报告说有一个"not-freed   block",但这个block是reachable的,所以它不算是真正的memory   leak.   
    
  2)   如果使用的是局部指针:   
  int   main()   
  {   
          int   *pi;     //   use   local   pointer:   real   memory   leak!!!   
          pi   =   new   int[100];   
          return   0;   
  }   
    
    
  ==13782==   searching   for   pointers   to   1   not-freed   blocks.   
  ==13782==   checked   4484352   bytes.   
  ==13782==   
  ==13782==   4   bytes   in   1   blocks   are   definitely   lost   in   loss   record   1   of   1   
  ==13782==         at   0xB74D27AB:   __builtin_new   (vg_replace_malloc.c:172)   
  ==13782==         by   0xB74D2802:   operator   new(unsigned)   (vg_replace_malloc.c:185)   
  ==13782==         by   0x8048491:   main   (in   /home/prog/valgrind/memtest)   
  ==13782==         by   0xB71C4BA6:   __libc_start_main   (in   /lib/libc-2.3.2.so)   
  ==13782==   
  ==13782==   LEAK   SUMMARY:   
  ==13782==         definitely   lost:   4   bytes   in   1   blocks.   
  ==13782==         possibly   lost:       0   bytes   in   0   blocks.   
  ==13782==         still   reachable:   0   bytes   in   0   blocks.   
  ==13782==                   suppressed:   0   bytes   in   0   blocks.   
  ==13782==   

  报告说是"definitely   lost",这才是真正的memory   leak!   



本文标签: 内存valgrind