【问题标题】:Compiling with maximum debugging symbols and lowest optimizations still skips pieces of code使用最大调试符号和最低优化进行编译仍然会跳过代码片段
【发布时间】:2019-08-12 05:19:48
【问题描述】:

重现步骤:

  • 克隆 emacs 存储库
    • git clone https://github.com/emacs-mirror/emacs.git
  • 运行样板程序以准备构建/创建 Makefile
    • i@user:~/emacs$ ./autogen.sh; ./configure
  • 导航到目录lib-src/ 以构建etags 二进制文件
    • cd lib-src/
  • 通过编辑lib-src/ 目录中的Makfile,确保我编译的etags 二进制文件具有最多的调试符号和尽可能少的优化

    • CC=gcc
    • CFLAGS=-fno-eliminate-unused-debug-types -g3 -O0
    • CPPFLAGS =
    • LDFLAGS =
  • 构建etags 二进制目标

    • make tags
  • 只需在gdb 中使用如下参数进行简单的测试运行,即可测试在调试时不会跳过任何代码:etags --help
gdb etags
(gdb) b main
Breakpoint 1 at 0x37ca: file etags.c, line 1071.
(gdb) r
Starting program: /home/i/emacs/lib-src/etags 
Breakpoint 1, main (argc=1, argv=0x7fffffffdfb8) at etags.c:1071
1071    {
(gdb) n
1078      bool help_asked = false;
(gdb) n
1083      progname = argv[0];
(gdb) n
1084      nincluded_files = 0;
(gdb) n
1085      included_files = xnew (argc, char *);
(gdb)

如您所见,gdb 跳过了对应于以下代码的第 1072-1077 行:

// ...
// ...
// ...
int                             // Line 1069
main (int argc, char **argv)    // Line 1070
{                               // Line 1071
  int i;                        // Line 1072
  unsigned int nincluded_files; // Line 1073
  char **included_files;        // Line 1074
  argument *argbuffer;          // Line 1075
  int current_arg, file_count;  // Line 1076
  linebuffer filename_lb;       // Line 1077
  bool help_asked = false;      // Line 1078
  ptrdiff_t len;                // Line 1079
  char *optstring;              // Line 1080
  int opt;                      // Line 1081
// ...
// ...
// ...

我错过了什么吗?我是否应该添加一个标志以确保在生成调试符号时不会跳过任何代码行?

【问题讨论】:

  • 要真正理解这一点,您需要查看汇编代码。您会发现有一个函数序言为所有变量分配了足够的堆栈空间(通常通过从堆栈指针中减去预先计算的值)。所以对于像 1072 这样的行没有任何代码。i 的内存在函数序言中分配,以及所有其他变量的内存(第 73 到 77 行和 79 到 81 行)。第 78 行是唯一实际做某事的行(除了声明一个变量)。

标签: c debugging gcc gdb


【解决方案1】:

我错过了什么吗?

是的:第 1072-1077 行是声明,编译器不会为它们发出任何可执行代码。

next 的工作方式是:一次单步执行程序一条指令,直到当前行与当前行不匹配 next 执行开始时的当前行(即,如果您当前停止在第 X 行, 单步直到当前行 != X),然后停止。

由于没有指示停止对应于 1072 和 1077 之间的任何行,因此单步执行一次即可立即到达 1078 行。

这是按设计工作的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-25
    • 1970-01-01
    • 2011-03-29
    • 1970-01-01
    相关资源
    最近更新 更多