Valgrind:可能丢失可以被视为绝对丢失吗?

Posted

技术标签:

【中文标题】Valgrind:可能丢失可以被视为绝对丢失吗?【英文标题】:Valgrind: can possibly lost be treated as definitely lost? 【发布时间】:2010-08-21 12:58:41 【问题描述】:

我可以将 Valgrind memcheck 的输出“可能丢失”视为“肯定丢失”吗?

可能丢失或“可疑”:找到了指向块内部的指针。指针最初可能已指向开始和 已经被移动了,或者它可能完全不相关。内存检查 认为这样的区块是“可疑的”,因为不清楚 指向它的指针仍然存在。

肯定丢失或“泄露”:最坏的结果是找不到指向该块的指针。该区块被归类为“泄露”, 因为程序员不可能在程序中释放它 退出,因为不存在指向它的指针。这很可能是以下症状 在程序中的某个较早点丢失了指针

【问题讨论】:

【参考方案1】:

是的,我建议将可能丢失肯定丢失一样严重。换句话说,修复你的代码,直到没有任何损失。

当您使用持有该数组的同一指针遍历数组时,可能会发生丢失。 知道你可以通过减去索引来重置指针。但是 valgrind 无法判断这是编程错误还是您是 聪明 故意这样做的。这就是它警告您的原因。

示例

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char** argv) 
  char* s = "string";
  // this will allocate a new array
  char* p = strdup(s);
  // move the pointer into the array
  // we know we can reset the pointer by subtracting
  // but for valgrind the array is now lost
  p += 1;
  // crash the program
  abort();
  // reset the pointer to the beginning of the array
  p -= 1;
  // properly free the memory for the array
  free(p);
  return 0;

编译

$ gcc -ggdb foo.c -o foo

Valgrind 报告

$ valgrind ./foo
...
==31539== Process terminating with default action of signal 6 (SIGABRT): dumping core
==31539==    at 0x48BBD7F: raise (in /usr/lib/libc-2.28.so)
==31539==    by 0x48A6671: abort (in /usr/lib/libc-2.28.so)
==31539==    by 0x10917C: main (foo.c:14)
==31539== 
==31539== HEAP SUMMARY:
==31539==     in use at exit: 7 bytes in 1 blocks
==31539==   total heap usage: 1 allocs, 0 frees, 7 bytes allocated
==31539== 
==31539== LEAK SUMMARY:
==31539==    definitely lost: 0 bytes in 0 blocks
==31539==    indirectly lost: 0 bytes in 0 blocks
==31539==      possibly lost: 7 bytes in 1 blocks
==31539==    still reachable: 0 bytes in 0 blocks
==31539==         suppressed: 0 bytes in 0 blocks

...

如果你删除abort(),那么 Valgrind 将报告没有任何内存丢失。不中止,指针将返回数组的开头,内存将正确地为freed。

这是一个简单的例子。在足够复杂的代码中,指针可以并且将返回到内存块的开头不再是显而易见的。代码其他部分的更改可能会导致可能丢失变成肯定丢失。这就是为什么你应该关心可能丢失

【讨论】:

有点迟到的吹毛求疵……*s = 'S' 是未定义的行为。它可能会出现段错误,它可能会更改s 指向的字符串,什么都不做,或者导致编译器优化整个程序,例如,取决于操作系统和编译器。 (我宁愿打电话给便携式std::terminate()。) 感谢您的提醒。我用abort() 更新了代码。我认为这相当于std::terminate()

以上是关于Valgrind:可能丢失可以被视为绝对丢失吗?的主要内容,如果未能解决你的问题,请参考以下文章

Valgrind 报告内存肯定丢失而没有错误

VS2010 数据库项目部署,如果可能发生数据丢失会失败吗?

RabbitMQ 和 Kafka 的消息可靠性对比

关于kafka数据丢失场景的一次激烈讨论....

硬盘重要资料丢失,用软件恢复无效,要抓狂了!

Valgrind vs Purify [关闭]