【问题标题】:MPI debugging with GDB - No symbol "i" in current context使用 GDB 进行 MPI 调试 - 当前上下文中没有符号“i”
【发布时间】:2014-12-30 23:49:52
【问题描述】:

我需要调试用 C 编写的 MPI 应用程序。我想使用将 GDB 手动附加到进程的系统,推荐使用 here(第 6 段)。

问题是,当我尝试打印变量“i”的值时,我得到了这个错误:

No symbol "i" in current context.

set var i=5 也有同样的问题。当我尝试运行info local 时,它只是声明“无语言环境”。

  • 系统 Ubuntu 14.04
  • MPICC cc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
  • GDB GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1。

我用命令编译我的代码

mpicc -o hello hello.c

并执行它

mpiexec -n 2 ./hello

我试图寻找这个问题,但解决方案通常是在 GCC 中不使用任何优化 (-O) 选项,但这对我来说没有用,因为我在这里没有使用它们中的任何一个,我正在使用 MPICC 进行编译。我已经尝试将“i”变量声明为volatile,并使用-g-O0 启动mpicc,但没有任何帮助。


DBG 消息

GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1

Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
Attaching to process 3778
Reading symbols from /home/martin/Dokumenty/Programovani/mpi_trenink/hello...done.
Reading symbols from /usr/lib/x86_64-linux-gnu/libmpich.so.10...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/x86_64-linux-gnu/libmpich.so.10
Reading symbols from /lib/x86_64-linux-gnu/libc.so.6...Reading symbols from /usr/lib/debug//lib/x86_64-linux-gnu/libc-2.19.so...done.
done.
Loaded symbols for /lib/x86_64-linux-gnu/libc.so.6
Reading symbols from /usr/lib/x86_64-linux-gnu/libmpl.so.1...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/x86_64-linux-gnu/libmpl.so.1
Reading symbols from /lib/x86_64-linux-gnu/librt.so.1...Reading symbols from /usr/lib/debug//lib/x86_64-linux-gnu/librt-2.19.so...done.
done.
Loaded symbols for /lib/x86_64-linux-gnu/librt.so.1
Reading symbols from /usr/lib/libcr.so.0...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/libcr.so.0
Reading symbols from /lib/x86_64-linux-gnu/libpthread.so.0...Reading symbols from /usr/lib/debug//lib/x86_64-linux-gnu/libpthread-2.19.so...done.
done.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Loaded symbols for /lib/x86_64-linux-gnu/libpthread.so.0
Reading symbols from /lib/x86_64-linux-gnu/libgcc_s.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib/x86_64-linux-gnu/libgcc_s.so.1
Reading symbols from /lib64/ld-linux-x86-64.so.2...Reading symbols from /usr/lib/debug//lib/x86_64-linux-gnu/ld-2.19.so...done.
done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
Reading symbols from /lib/x86_64-linux-gnu/libdl.so.2...Reading symbols from /usr/lib/debug//lib/x86_64-linux-gnu/libdl-2.19.so...done.
done.
Loaded symbols for /lib/x86_64-linux-gnu/libdl.so.2
Reading symbols from /lib/x86_64-linux-gnu/libnss_files.so.2...Reading symbols from /usr/lib/debug//lib/x86_64-linux-gnu/libnss_files-2.19.so...done.
done.
Loaded symbols for /lib/x86_64-linux-gnu/libnss_files.so.2
0x00007f493e53c9a0 in __nanosleep_nocancel ()
    at ../sysdeps/unix/syscall-template.S:81
81  ../sysdeps/unix/syscall-template.S: No such file or directory.

我的代码

#include <stdio.h>
#include <mpi.h>

#include <unistd.h> // sleep()

int main(){
    MPI_Init(NULL, NULL);
    
    /* DEBUGGING STOP */

    int i = 0;
    while(i == 0){
        sleep(30);
    }

    int world_size;
    MPI_Comm_size( MPI_COMM_WORLD, &world_size );

    int process_id; // casto znaceno jako 'world_rank'
    MPI_Comm_rank( MPI_COMM_WORLD, &process_id );

    char processor_name[ MPI_MAX_PROCESSOR_NAME ];
    int name_len;
    MPI_Get_processor_name( processor_name, &name_len );

    printf("Hello! - sent from process %d running on processor %s.\n\
        Number of processors is %d.\n\
        Length of proc name is %d.\n\
        ***********************\n",
        process_id, processor_name, world_size, name_len);

    MPI_Finalize();
    return 0;
}

【问题讨论】:

  • 我试过了,还是不行:-(
  • 你能看到任何个变量吗?
  • 当我运行info local 时,我看不到任何变量。当我运行info variables 时,我看到很多以“__libc”等开头的变量。
  • 听起来 gcc 正在注册所有内容。如果你可以在 GDB 中使用disas main,那么就有可能弄清楚 GCC 使用什么寄存器来表示i。然后您可以运行info reg 来确定该特定时间的值。我很乐意帮助分析程序集以找出寄存器是什么,但很抱歉我没有更好的答案来解释为什么您迄今为止的尝试都没有结果。
  • 您确定要附加到 MPI 进程而不是父 mpiexec

标签: c ubuntu gdb mpi


【解决方案1】:

GDB 很有可能在深入执行sleep(3) 函数时中断进程。您可以通过首先发出bt(回溯)命令来检查:

(gdb) bt
#0  0x00000030e0caca3d in nanosleep () from /lib64/libc.so.6
#1  0x00000030e0cac8b0 in sleep () from /lib64/libc.so.6
#2  0x0000000000400795 in main (argc=1, argv=0x7fff64ae4688) at sleeper.c:9

i 不在nanosleep 的框架中:

(gdb) info locals
No symbol table info available.

通过发出frame x 命令选择main 函数的堆栈帧(其中x 是帧号,在所示示例中2)。

(gdb) f 2
#2  0x0000000000400795 in main (argc=1, argv=0x7fff64ae4688) at sleeper.c:9
9          while(i == 0) { sleep(30); }

i 现在应该在那里:

(gdb) info locals
i = 0

如果 GDB 碰巧附加到错误的线程,您可能还需要更改活动线程。许多 MPI 库产生额外的线程,例如使用英特尔 MPI:

(gdb) info threads
  3 Thread 0x7f8b9fada700 (LWP 39085)  0x00000030e0cdf1b3 in poll () from /lib64/libc.so.6
  2 Thread 0x7f8b9f0d9700 (LWP 39087)  0x00000030e0cdf1b3 in poll () from /lib64/libc.so.6
* 1 Thread 0x7f8ba1b51700 (LWP 39066)  0x00000030e0caca3d in nanosleep () from /lib64/libc.so.6

标有* 的线程是正在检查的线程。如果其他线程处于活动状态,请使用thread 1 命令切换到主线程。

【讨论】:

  • 我看到我们找到了几乎相同的解决方案 :-)
  • 顺便说一句,让进程等待调试器的更简单的方法是raise(SIGSTOP);。这通过使其向自身发送SIGSTOP 信号来停止调用进程。一旦你附加到它,放置一个断点并给 GDB cont 命令。请注意,该过程将在raise(3) 调用内停止,因此您还需要发出upframe x
【解决方案2】:

我终于解决了这个问题。关键是在尝试向上打印变量“i”或更改其值之前,我必须使用 up 命令检查特定帧的内容。


分步解决方案

  1. 使用mpicc -o hello hello.c -g -O0 编译此代码。 使用mpiexec -n 2 ./hello 启动程序。

  2. 找出进程ID(PID)。

    • 我使用命令ps -e | grep hello
    • 其他选项是简单地使用pstree
    • 最后,您可以使用原生 Linux 函数getpid()
  3. 下一步是打开一个新终端并使用命令gdb --pid debugged_process_id 启动GDB。

  4. 现在,在调试器中输入 bt。 输出将与此类似:

    #0  0x00007f63667e09a0 in __nanosleep_nocancel ()
    at ../sysdeps/unix/syscall-template.S:81
    #1  0x00007f63667e0854 in __sleep (seconds=0)
    at ../sysdeps/unix/sysv/linux/sleep.c:137
    #2  0x00000000004009ec in main () at hello.c:20
    
  5. 如我们所见,第 2 段指向代码 hello.c,因此我们可以更详细地查看它。输入up 2。 输出将与此类似:

    #2  0x00000000004009ec in main () at hello.c:20
    warning: Source file is more recent than executable.
    20          sleep(30);
    
  6. 最后,现在我们可以打印出这个块中的所有局部变量。输入info local。 输出:

    i = 0
    world_size = 0
    process_id = 0
    processor_name = "\000\000\000\000\000\000\000\000 5\026gc\177\000\000\200\306Η\377\177\000\000p\306Η\377\177\000\000.N=\366\000\000\000\000\272\005@\000\000\000\000\000\377\377\377\377\000\000\000\000%0`\236\060\000\000\000\250\361rfc\177\000\000x\n\026gc\177\000\000\320\067`\236\060\000\000\000\377\377\377\177\376\377\377\377\001\000\000\000\000\000\000\000\335\n@\000\000\000\000\000\377\377\377\377\377\377\377\377\000\000\000\000\000\000\000"
    name_len = 1718986550
    
  7. 现在我们可以通过set var i=1 释放停止循环并继续调试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-21
    相关资源
    最近更新 更多