valgrind-hellgrind与泄漏检查的结果不同

时间:2018-11-05 14:29:02

标签: c++ c valgrind

我有一些我不理解的奇怪行为。该代码有点复杂,因此我不打算在此处发布代码,而是描述行为,并且希望知道了valgrind的工作原理的人有一个想法,尽管了解的信息很少,我还是可以追求

背景:

我正在为基于开源c / c ++的基于代理的建模平台fork @ my github开发一些附加功能。编译很好。根据我对测试程序的验证,到目前为止,一切似乎都可以正常进行。另外,valgrind不会报告任何相关错误。但是,重现性(至关重要)很奇怪。

在框架内定义了一个模型文件(基本上是模拟运行的初始化)。基于此文件,应该能够再现完全相同的输出(与平台无关)。在某种程度上可以起作用:如果启动仿真环境(GUI版本),加载并运行文件,则每次生成的结果相同。另外,使用命令行版本,每次都能得到相同的结果。

但是,如果从一个正在运行的模拟环境实例中,我多次运行同一个模型,那么就会发生奇怪的行为-有时...

使用的编译器选项:

CC=g++
GLOBAL_CC=-march=native -std=gnu++14
SSWITCH_CC=-fnon-call-exceptions -Og -ggdb3 -Wall

设置:

我运行已编译的文件,然后在已编译的程序内部运行三次固定的仿真设置。现在,它每次应产生完全相同的结果,我通过在不同阶段打印随机数来进行检查。

奇怪的行为:

选项1:

当我使用以下选项在valgrind中运行程序时:

valgrind --leak-check=full --leak-resolution=high --show-reachable=yes

我内部没有得到相同的结果

选项1的报告

Finished processing sim1
==6206==
==6206== HEAP SUMMARY:
==6206==     in use at exit: 43 bytes in 1 blocks
==6206==   total heap usage: 4,124,309 allocs, 4,124,308 frees, 888,390,511 bytes allocated
==6206==
==6206== 43 bytes in 1 blocks are still reachable in loss record 1 of 1
==6206==    at 0x4C2DDCF: realloc (vg_replace_malloc.c:785)
==6206==    by 0x5BE7FB2: getcwd (getcwd.c:84)
==6206==    by 0x143391: lsdmain(int, char**) (lsdmain.cpp:203)
==6206==    by 0x10C37D: main (main_gnuwin.cpp:29)
==6206==
==6206== LEAK SUMMARY:
==6206==    definitely lost: 0 bytes in 0 blocks
==6206==    indirectly lost: 0 bytes in 0 blocks
==6206==      possibly lost: 0 bytes in 0 blocks
==6206==    still reachable: 43 bytes in 1 blocks
==6206==         suppressed: 0 bytes in 0 blocks
==6206==
==6206== For counts of detected and suppressed errors, rerun with: -v
==6206== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

选项#2

但是,当我改用以下选项时:

valgrind --tool=helgrind

每次使用命令行版本时,我的确得到相同的结果。有趣的是,选项#1的第一个结果与选项#2的结果相同。

我很乐意提出任何建议。而且,我不是训练有素的计算机科学家...我使用的是mt1937(每次都重新初始化)-但是模拟之间的初始随机数相同,因此我认为错误不存在于此。尽管稍后运行中选项#1中的随机数会发生变化(这是我的测试,除了模拟需要找到平衡点的时间之外)。

1 个答案:

答案 0 :(得分:1)

最后,我能找到问题所在:在程序的两点上,我对一个临时矢量进行了排序,该矢量带有成对的距离值和位于2d空间上的对象的指针:

std::sort( vector.begin(),vector.end() ); // vector of std::pairs<double, pointer>

显然,解决方案是仅按该对的第一项进行排序:

std::sort( vector.begin(),vector.end(), [](auto const &A, auto const &B ){return A.first < B.first; } );

关于为什么我没有直接发现此问题的一些评论:

  • 实施这种排序时,我打算使其“稳定”。对象的指针是唯一的,因此在不同的子集中,顺序是相同的,并且与我将项目添加到集合中的方式无关。
  • 我不认为指针值是(不是精确地但实际上是)我控制范围之外的随机数。
  • 我没有看到这一点,因为以某种方式OS(或其他任何方式)总是在程序的不同调用之间分配相同的指针值(我建议有一个“虚拟”空间,该空间总是被再次初始化)。因此,我不建议使用指针作为问题。
  • 奇怪的是,当我使用Valgrind和--tool=helgrind选项运行程序时,该问题并未持续。我得到的一个建议(离线)是memcheck使用给定的模式预先初始化内存,如果原因是未初始化的变量,这将是一个答案。看起来,Helgrind还在不同范围内控制内存,为我的每个后续模拟提供了“新鲜”虚拟内存,以使我的指针排序在重复循环中保持稳定。

我希望这对某人遇到同样的问题有帮助。感谢您的所有建议!