我需要在新机器上运行一个相当大的软件包才能工作。该应用程序是用C和C ++编写的,我在CentOS 6.5上运行。
该程序构建正常,但在我运行它时会出现段错误。使用valgrind,我看到在segfault的位置报告了以下错误:
==23843== Invalid read of size 4
[stack trace here]
==23843== Address 0x642e7464 is not stack'd, malloc'd or (recently) free'd
因此,出于某种原因,我们正在从内存中读取我们不应该并且正在调用未定义的行为。当我查看我的源文件时,将它们带到另一台CentOS 6.5机器(带有相同的内核)并编译它们(使用相同的makefile和相同的GCC版本)程序似乎运行正常。
我也在那台机器上运行了valgrind,并期望再次看到无效的读取。我的想法是无效的读取总是存在,但由于行为未定义,事情恰好在一台机器上正常工作而在另一台机器上没有。
然而,我发现valgrind报告第二台机器上没有读取错误。怎么可能这样呢?
答案 0 :(得分:3)
Valgrind使运行环境更具确定性,但并未消除所有随机性。也许其他机器安装了不同版本的库,或者它使用的任何外部文件(文件,网络......)都不同,代码执行不必完全相同。
您应该查看堆栈跟踪并分析发生错误的代码。如果仅从堆栈跟踪中看不明显,则可以使用valgrind
参数启动--vgdb=full
。一旦发生错误,它将暂停执行并打印出如何附加gdb
的说明。或者你可以直接在调试器下运行程序 - 你写道它甚至在没有valgrind的情况下崩溃。
答案 1 :(得分:0)
根据您提供的稀疏信息判断,不同的库版本是最好的猜测。要尝试的事情:
1)通过包管理器使两台机器都是最新的,然后再试一次
2)运行ldd [binary]
以查看相关程序使用的所有库。在两台机器上运行类似md5sum
的内容,以查明是否存在差异。
总的来说,我的经验是valgrind在检测堆栈上的无效内存访问时非常糟糕,所以这可能是一个隐藏的根本原因。如果所有其他方法都失败了,您可能想尝试使用clang和address sanitizer。它可能会发现valgrind无法捕获的东西,反之亦然。
答案 2 :(得分:0)
这可能是由于使用了不同版本的Valgrind。
在较新版本中会删除一些常见的误报错误。这可以解释为什么一台机器抱怨它(旧版本)而另一台机器不抱怨(较新版本)。