3

我编写了一个大型程序,并且很难追踪分段错误。我发布了一个问题,但我没有足够的信息继续下去(请参阅下面的链接 - 如果你这样做了,请注意,我花了几乎一整天的时间尝试多次想出一个最小可编译的代码版本来重现错误无济于事)。

https://stackoverflow.com/questions/16025411/phantom-bug-involving-stdvectors-mpi-c

所以现在我第一次尝试使用 valgrind。我刚刚安装了它(只是“sudo apt-get install valgrind”),没有特殊安装来解释 MPI(如果有的话)。我希望提供包括文件名和行号在内的具体信息(我知道 valgrind 不可能提供变量名)。当我得到有用的信息时,包括

  • 大小为 4 的无效读取
  • 条件跳转或移动取决于未初始化的值
  • 未初始化的值是由堆栈分配创建的
  • 1 个块中的 4 个字节肯定会丢失

除了这个神奇的东西

  • 系统调用参数 sched_setaffinity(mask) 指向 0x433CE77 处的不可寻址字节:系统调用 (syscall.S:31) 地址 0x0 未堆栈、malloc 或(最近)释放

我没有得到文件名和行号。相反,我得到

==15095==    by 0x406909A: ??? (in /usr/lib/openmpi/lib/libopen-rte.so.0.0.0)

这是我编译代码的方式:

mpic++ -Wall -Wextra -g -O0 -o Hybrid.out (…file names)

这是我执行 valgrind 的两种方法:

valgrind --tool=memcheck --leak-check=full --track-origins=yes --log-file=log.txt mpirun -np 1 Hybrid.out

mpirun -np 1 valgrind --tool=memcheck --leak-check=full --track-origins=yes --log-file=log4.txt -v ./Hybrid.out

第二个版本基于中的说明

当我使用 Open MPI 运行并行程序时出现分段错误

如果我正确理解选择的答案,这似乎与

带有 valgrind 的 openmpi(我可以在 Ubuntu 发行版中使用 MPI 进行编译吗?)

我故意在一个处理器上运行 valgrind,因为这是我的程序在没有分段错误的情况下执行完成的唯一方法。我也用两个处理器运行它,并且我的程序段出现了预期的错误,但我从 valgrind 得到的日志似乎包含基本相同的信息。我希望通过解决 valgrind 在一个处理器上报告的问题,我将神奇地解决不止一个处理器上发生的问题。

我尝试按照建议在程序编译中包含“-static”

尽管有 -g 标志,Valgrind 不显示行号(在 Ubuntu 11.10/VirtualBox 上)

但编译失败,说(除了几个警告)

dynamic STT_GNU_IFUNC symbol "strcmp" with pointer equality in '…' can not be used when making an executably; recompile with fPIE and relink with -pie

我还没有研究过“fPIE”和“-pie”是什么意思。另外,请注意我没有使用 makefile,我目前也不知道如何编写。

还有一些注意事项:我的代码不使用命令 malloc、calloc 或 new。我完全使用 std::vector; 没有 C 数组。我确实使用 .resize()、.insert()、.erase() 和 .pop_back() 等命令。我的代码还通过引用和常量引用将向量传递给函数。至于并行命令,我只使用 MPI_Barrier()、MPI_Bcast() 和 MPI_Allgatherv()。

如何让 valgrind 显示它报告的错误的文件名和行号?谢谢大家的帮助!

编辑

我继续研究它,我的一个朋友指出没有行号的报告都是来自 MPI 文件,我没有从源代码编译,并且由于我没有编译它们,我不能使用 -g 选项,因此看不到线条。所以我根据这个命令再次尝试了valgrind,

mpirun -np 1 valgrind --tool=memcheck --leak-check=full --track-origins=yes --log-file=log4.txt -v ./Hybrid.out

但现在对于两个处理器,即

mpirun -np 2 valgrind --tool=memcheck --leak-check=full --track-origins=yes --log-file=log4.txt -v ./Hybrid.out

程序运行完成(我没有看到命令行中报告的 seg 错误)但是 valgrind 的执行确实给了我文件中的行号。valgrind 指向的行是我调用 MPI_Bcast() 的行。可以肯定地说这是因为内存问题仅在多个处理器上表现出来(因为我已经在 np -1 上成功运行它)?

4

1 回答 1

0

听起来您使用了错误的工具。如果您想知道分段错误发生在哪里,请使用 gdb。

这是一个简单的例子。该程序将在*b=5

// main.c

int
main(int argc, char** argv)
{
   int* b = 0;
   *b = 5;
   return *b;
}

使用 gdb 查看发生了什么;(<---- 部分解释输入行)

svengali ~ % g++ -g -c main.c -o main.o # include debugging symbols in .o file
svengali ~ % g++ main.o -o a.out        # executable is linked (no -g here)
svengali ~ % gdb a.out
GNU gdb (GDB) 7.4.1-debian
<SNIP>
Reading symbols from ~/a.out...done.
(gdb) run <--------------------------------------- RUNS THE PROGRAM
Starting program: ~/a.out 

Program received signal SIGSEGV, Segmentation fault.
0x00000000004005a3 in main (argc=1, argv=0x7fffffffe2d8) at main.c:5
5      *b = 5;
(gdb) bt  <--------------------------------------- PRINTS A BACKTRACE
#0  0x00000000004005a3 in main (argc=1, argv=0x7fffffffe2d8) at main.c:5
(gdb) print b <----------------------------------- EXAMINE THE CONTENTS OF 'b'
$2 = (int *) 0x0
(gdb) 
于 2013-05-27T16:49:38.203 回答