【问题标题】:Why are some statements skipped in gdb?为什么在 gdb 中跳过了一些语句?
【发布时间】:2011-06-04 03:20:35
【问题描述】:

我正在调试这段代码:

len = NGX_SYS_NERR * sizeof(ngx_str_t);

ngx_sys_errlist = malloc(len);
if (ngx_sys_errlist == NULL) {
    goto failed;
}

for (err = 0; err < NGX_SYS_NERR; err++) {

但是在gdb中if (ngx_sys_errlist == NULL) {被直接跳过了:

(gdb) 
59      ngx_sys_errlist = malloc(len);
(gdb) n
64      for (err = 0; err < NGX_SYS_NERR; err++) {

我也遇到过,不知道是什么原因,有谁知道吗?

这是一个错误吗?

更新

0x000000000041be9d <ngx_strerror_init+0>:   mov    %rbx,-0x30(%rsp)
0x000000000041bea2 <ngx_strerror_init+5>:   mov    %rbp,-0x28(%rsp)
0x000000000041bea7 <ngx_strerror_init+10>:  mov    %r12,-0x20(%rsp)
0x000000000041beac <ngx_strerror_init+15>:  mov    %r13,-0x18(%rsp)
0x000000000041beb1 <ngx_strerror_init+20>:  mov    %r14,-0x10(%rsp)
0x000000000041beb6 <ngx_strerror_init+25>:  mov    %r15,-0x8(%rsp)
0x000000000041bebb <ngx_strerror_init+30>:  sub    $0x38,%rsp
0x000000000041bebf <ngx_strerror_init+34>:  mov    $0x840,%edi
0x000000000041bec4 <ngx_strerror_init+39>:  callq  0x402388 <malloc@plt>
0x000000000041bec9 <ngx_strerror_init+44>:  mov    %rax,0x26e718(%rip)        # 0x68a5e8 <ngx_sys_errlist>
0x000000000041bed0 <ngx_strerror_init+51>:  mov    $0x840,%r12d
0x000000000041bed6 <ngx_strerror_init+57>:  test   %rax,%rax
0x000000000041bed9 <ngx_strerror_init+60>:  je     0x41bf56 <ngx_strerror_init+185>
0x000000000041bedb <ngx_strerror_init+62>:  mov    $0x0,%r13d
0x000000000041bee1 <ngx_strerror_init+68>:  mov    $0x0,%r14d
0x000000000041bee7 <ngx_strerror_init+74>:  mov    $0x0,%r15d
0x000000000041beed <ngx_strerror_init+80>:  mov    %r13d,%edi
0x000000000041bef0 <ngx_strerror_init+83>:  callq  0x402578 <strerror@plt>

更新

没有其他人在使用 gdb 时遇到过同样的事情吗?调试时经常发生在我身上。

【问题讨论】:

  • 不要使用 goto。为了大家。
  • 你有调试器,看看生成的汇编代码。
  • @Dani:很抱歉,但这看起来像是对goto 的完全有效使用。我猜failed 标签位于函数的底部(在正常的return 之后)并且在一些清理代码之前。如果我是对的,那么这对goto 来说是一份完美的工作,其他任何事情都可能是一堆毫无意义的忙碌工作。
  • @mu 太短:goto 没有有效用途。它只是 c++ 所基于的任何语言的残余,没有函数调用。
  • @Dani:当您可以使用 try/catch 时,它会起作用,它不包括 C(C 等效项是 goto,或者对于嵌套函数 setjmp()/longjmp() goto 看起来很干净......)和一些嵌入式或受限上下文(例如,在中断下半部分正确处理将很难甚至不可能)。由于这是 C 代码(malloc() 而不是 new[]),因此您会得到 goto 甚至更丑陋且逻辑混乱的机制,例如虚拟循环。

标签: gdb


【解决方案1】:

这两条语句很可能被优化为一个单独的设置和测试表达式,然后无法分解为原始的两行。生成的伪代码可能类似于

call _malloc
jz _failed
mov acc, _ngx_sys_errlist

现在在分配之前进行测试的地方;您是否让源级跟踪向后反映这一点?

【讨论】:

  • @geekosaur,看看我的更新,我想它还在那里:je 0x41bf56 &lt;ngx_strerror_init+185&gt;
  • @compile-fan: IIRC 在 x86 上测试零的常用方法类似于 oring %eax 本身,然后根据需要执行 jejne,所以你很可能完全符合我的建议。
  • 正如我们在程序集中看到的,它没有被优化出来。
  • @geekosaur,我刚刚用谷歌搜索了test %rax %rax,似乎它也是检查%rax 是否为0 的有效用途。你可以检查这个答案:stackoverflow.com/questions/147173/…
  • 除了%rax 是x86-64,而不是x86,test 在道德上与or 相同。我认为哪个更快取决于处理器的生成(过去几年生产的任何产品可能总是更快;我不需要关心这个世纪:)。
【解决方案2】:

请检查,
a) 如果您正在调试发布版本(如果存在)
b) 如果你的源文件被修改了

如果仍有问题,请提供详细信息(编译器版本、调试器版本、平台和代码...)

【讨论】:

    猜你喜欢
    • 2014-06-04
    • 2016-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-25
    相关资源
    最近更新 更多