Debugging 如何转到GDB中的上一行?

Debugging 如何转到GDB中的上一行?,debugging,gdb,Debugging,Gdb,在gdb中是否可以转到当前执行行之前的行。 e、 g: 我目前在b行,可以检查那里的arr值,但我想回到a行,检查arr的内容 我认为这可能是不可能的,因为调试器可以慢动作运行代码,但不能使其向后执行。 还有更多的见解。根据,以及“如果目标环境支持它”,是的。如果您的程序很短,通常的技巧是 在前一行放置一个新断点 激发r以重新启动调试 GDB就是为了这样做的 每个人都希望有这样一个无所不知的调试器:,但它们(取决于语言/机器)很难制作,而且有很多簿记工作要做 目前,在真正的硬件上,而不是在虚

在gdb中是否可以转到当前执行行之前的行。 e、 g:

我目前在b行,可以检查那里的
arr
值,但我想回到a行,检查
arr
的内容

我认为这可能是不可能的,因为调试器可以慢动作运行代码,但不能使其向后执行。

还有更多的见解。

根据,以及“如果目标环境支持它”,是的。

如果您的程序很短,通常的技巧是

  • 在前一行放置一个新断点
    • 激发
      r
      以重新启动调试

  • GDB就是为了这样做的

    每个人都希望有这样一个无所不知的调试器:,但它们(取决于语言/机器)很难制作,而且有很多簿记工作要做


    目前,在真正的硬件上,而不是在虚拟机上,这几乎是不可能做到的。

    简短回答:不

    有关解决方法,请阅读下面的内容

    虽然在b行不可能确定a行的值,但可以通过只命中一个断点来记录a和b以及其他位置的arr值

    • 使用“display”命令(display variable_name,其中variable_name将替换为arr、*arr、**arr,具体取决于您要查找的内容),以便在命中任何断点时,变量_name的内容将转储到屏幕上。请注意,当variabe_名称在范围内时,可以将其添加到显示列表中,这样可能需要等待第一个断点
    • 在您感兴趣的代码的不同位置创建断点,以便记录变量\u name的值。其中一个断点位于a行
    • 对于每个断点,使用命令(命令断点编号)并指示断点不要停止程序的执行。您需要使用的命令是continue,后跟end。见下面的例子
    (gdb)命令1

    键入有关何时命中断点1的命令,每行一个。用一句话结束,只说“结束”

    继续

    结束

    • 在b行上放置一个断点
    现在,当命中所有其他日志断点时,arr的值将转储到屏幕上,但断点不会等待用户交互,将自动继续。当您在b行点击一个断点时,您可以看到arr的过去值,这些值将记录在gdb本身中


    根据具体情况,您还可以转储(并显示)大量有用的信息。例如,如果在循环中调用上述函数10000次,您可能还希望转储循环计数器(例如i)。这真的取决于你想要实现什么。

    是的!使用新版本7.0 gdb,您可以做到这一点

    该命令将是“
    reverse step
    ”或“
    reverse next

    您可以从ftp.gnu.org:/pub/gnu/gdb获得gdb-7.0

    如果遇到错误:
    目标子级不支持此命令。
    然后尝试在执行开始时,在启动
    run
    后添加
    目标记录


    编辑:由于GDB 7.6
    目标记录
    已被弃用,请改用
    目标记录完整

    是的,现在使用真正的硬件(即不仅仅是虚拟机)是可能的,而且简单明了。 GDB-7.0支持在本机linux x86机器上使用反向步骤和反向继续等命令进行反向调试


    这里有一个教程:

    如果您的arr设置代码刚好在“行a”(一个非常常见的场景)上方,您可以这样做:

    tbreak myfilename.c:123
    (第123行是arr设置代码的开始),然后

    “tbreak”阻止gdb在跳转后继续(恢复)程序


    然后,您可以单步执行设置代码,或者只在“行a”处设置一个断点,然后继续执行

    而不是gdb,但您可以使用名为qira的调试器轻松地返回历史。您可以使用向上和向下箭头来回移动,它还会突出显示已更改的寄存器


    mozilla rr

    GDB的内置记录和重播具有严重的限制,例如不支持AVX指令:

    rr的正面:

    • 现在要可靠得多。我已经对几个复杂的软件进行了较长时间的测试
    • 还提供了带有gdbserver协议的GDB接口,使其成为一个很好的替代品
    • 对于大多数程序来说,性能下降很小,如果不进行测量,我自己也没有注意到
    • 生成的记录道在磁盘上很小,因为只记录了很少的非确定性事件,到目前为止,我从来不用担心它们的大小
    下面的示例展示了它的一些功能,特别是
    reverse next
    reverse step
    reverse continue
    命令

    在Ubuntu 18.04上安装:

    sudo apt-get install rr linux-tools-common linux-tools-generic linux-cloud-tools-generic
    sudo cpupower frequency-set -g performance
    # Overcome "rr needs /proc/sys/kernel/perf_event_paranoid <= 1, but it is 3."
    echo 'kernel.perf_event_paranoid=1' | sudo tee -a /etc/sysctl.conf
    sudo sysctl -p
    
    现在您被留在GDB会话中,您可以正确地反向调试:

    (rr) break main
    Breakpoint 1 at 0x55da250e96b0: file a.c, line 16.
    (rr) continue
    Continuing.
    
    Breakpoint 1, main () at a.c:16
    16          i = 0;
    (rr) next
    17          i = 1;
    (rr) print i
    $1 = 0
    (rr) next
    18          i = 2;
    (rr) print i
    $2 = 1
    (rr) reverse-next
    17          i = 1;
    (rr) print i
    $3 = 0
    (rr) next
    18          i = 2;
    (rr) print i
    $4 = 1
    (rr) next
    21          f();
    (rr) step
    f () at a.c:7
    7           i = 0;
    (rr) reverse-step
    main () at a.c:21
    21          f();
    (rr) next
    23          printf("i = %d\n", i);
    (rr) next
    i = 2
    27          i = time(NULL);
    (rr) reverse-next
    23          printf("i = %d\n", i);
    (rr) next
    i = 2
    27          i = time(NULL);
    (rr) next
    28          printf("time(NULL) = %d\n", i);
    (rr) print i
    $5 = 1509245372
    (rr) reverse-next
    27          i = time(NULL);
    (rr) next
    28          printf("time(NULL) = %d\n", i);
    (rr) print i
    $6 = 1509245372
    (rr) reverse-continue
    Continuing.
    
    Breakpoint 1, main () at a.c:16
    16          i = 0;
    
    rr通过首先以记录每个非确定性事件(如线程切换)发生的情况的方式运行程序来实现这一点

    然后在第二次重播运行期间,它使用该跟踪文件(其小得惊人)准确地重构在原始非确定性运行上发生的情况,但以确定性的方式,向前或向后

    rr最初是由Mozilla开发的,用于帮助他们重现第二天夜间测试中出现的计时错误。但是,对于只有在执行数小时内发生的错误,反向调试方面也很重要,因为您经常希望后退一步,检查前一种状态导致了后一种故障

    我认为rr最严重的限制是:

    • 您必须从中进行第二次重播
      sudo apt-get install rr linux-tools-common linux-tools-generic linux-cloud-tools-generic
      sudo cpupower frequency-set -g performance
      # Overcome "rr needs /proc/sys/kernel/perf_event_paranoid <= 1, but it is 3."
      echo 'kernel.perf_event_paranoid=1' | sudo tee -a /etc/sysctl.conf
      sudo sysctl -p
      
      #include <stdio.h>
      #include <stdlib.h>
      #include <time.h>
      
      int f() {
          int i;
          i = 0;
          i = 1;
          i = 2;
          return i;
      }
      
      int main(void) {
          int i;
      
          i = 0;
          i = 1;
          i = 2;
      
          /* Local call. */
          f();
      
          printf("i = %d\n", i);
      
          /* Is randomness completely removed?
           * Recently fixed: https://github.com/mozilla/rr/issues/2088 */
          i = time(NULL);
          printf("time(NULL) = %d\n", i);
      
          return EXIT_SUCCESS;
      }
      
      gcc -O0 -ggdb3 -o reverse.out -std=c89 -Wextra reverse.c
      rr record ./reverse.out
      rr replay
      
      (rr) break main
      Breakpoint 1 at 0x55da250e96b0: file a.c, line 16.
      (rr) continue
      Continuing.
      
      Breakpoint 1, main () at a.c:16
      16          i = 0;
      (rr) next
      17          i = 1;
      (rr) print i
      $1 = 0
      (rr) next
      18          i = 2;
      (rr) print i
      $2 = 1
      (rr) reverse-next
      17          i = 1;
      (rr) print i
      $3 = 0
      (rr) next
      18          i = 2;
      (rr) print i
      $4 = 1
      (rr) next
      21          f();
      (rr) step
      f () at a.c:7
      7           i = 0;
      (rr) reverse-step
      main () at a.c:21
      21          f();
      (rr) next
      23          printf("i = %d\n", i);
      (rr) next
      i = 2
      27          i = time(NULL);
      (rr) reverse-next
      23          printf("i = %d\n", i);
      (rr) next
      i = 2
      27          i = time(NULL);
      (rr) next
      28          printf("time(NULL) = %d\n", i);
      (rr) print i
      $5 = 1509245372
      (rr) reverse-next
      27          i = time(NULL);
      (rr) next
      28          printf("time(NULL) = %d\n", i);
      (rr) print i
      $6 = 1509245372
      (rr) reverse-continue
      Continuing.
      
      Breakpoint 1, main () at a.c:16
      16          i = 0;