10

我看到 valgrind 将内存泄漏分类为:

  • 肯定输了
  • 间接失去
  • 可能丢失
  • 仍然可以到达
  • 压制

我刚刚修复了“可能丢失”是主要问题的泄漏。

文档说:“可能丢失意味着您的程序正在泄漏内存,除非您使用可能导致它们指向已分配块中间的指针做不寻常的事情;有关一些可能的原因,请参阅用户手册

我可以知道一个“用指针做不寻常的事情,可能导致它们指向分配块的中间”的例子吗?

我的意思是一个可以忽略“可能丢失”的示例,尽管它是由 valgrind 报告的。使用指针使 valgrind 抱怨但同时以这种方式使用指针在某种程度上是合法的示例

谢谢

4

3 回答 3

9

文档的一些示例是具有自己的分配器的不同库,并且返回的内存不是直接由底层操作系统分配器(malloc/sbrk)返回的指针,而是偏移后的指针。例如,考虑一个分配器,它获得了一些额外的内存并存储了元信息(可能是垃圾收集器的类型信息......)。分配和解除分配的过程类似于:

void* allocate( size_t size ) {
   metainfo_t *m = (metainfo_t*) malloc( size + sizeof(metainfo) );
   m->data = some_value;
   return (void*)(m+1);          // [1]
}
void deallocate( void* p ) {
   metainfo_t *m = ((metainfo_t*)p) - 1;
   // use data
}
void * memory = allocate(10);

当 valgrind 跟踪内存时,它会记住由 返回的原始指针malloc,并且该指针不会存储在程序的任何位置。但这并不意味着内存已经泄漏,它只意味着指针在程序中不能直接使用。特别是memory仍然持有返回的指针,并且deallocate可以调用来释放它,但在程序的任何valgrind位置都看不到原始返回的指针(char*)memory - sizeof(metadata_t)并发出警告。

于 2012-07-31T12:18:17.240 回答
5
char *p = malloc(100);
if (p != 0)
{
    p += 50;
    /* at this point, no pointer points to the start of the allocated memory */
    /* however, it is still accessible */
    for (int i = -50; i != 50; i++)
        p[i] = 1;
    free (p - 50);
}
于 2012-07-31T11:23:00.597 回答
2
char *p = malloc(100);
if (p != 0)
{
    p += 50;
    /* at this point, no pointer points to the start of the allocated memory */
    /* however, it is still accessible */
    for (int i = -50; i != 50; i++)
        p[i] = 1;
    free (p - 50);
}

因为它看起来很有趣,所以我确实运行了代码并对其进行了 valgrind。结果如下。

yjaeyong@carbon:~$ valgrind test
==14735== Memcheck, a memory error detector
==14735== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==14735== Using Valgrind-3.6.1-Debian and LibVEX; rerun with -h for copyright info
==14735== Command: test
==14735== 
==14735== 
==14735== HEAP SUMMARY:
==14735==     in use at exit: 0 bytes in 0 blocks
==14735==   total heap usage: 32 allocs, 32 frees, 2,017 bytes allocated
==14735== 
==14735== All heap blocks were freed -- no leaks are possible
==14735== 
==14735== For counts of detected and suppressed errors, rerun with: -v
==14735== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 11 from 6)

它说不可能有泄漏。我错过了什么吗?

于 2012-07-31T13:20:43.630 回答