为什么gdb中会跳过一些语句?

为什么gdb中会跳过一些语句?,gdb,Gdb,我正在调试此代码: 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++) { 我以前也经历过这种情况,但从来都不知道原因,有人知道吗 是虫子吗 更新 0x000000000041be9d <ngx_strerro

我正在调试此代码:

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++) {
我以前也经历过这种情况,但从来都不知道原因,有人知道吗

是虫子吗

更新

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>
0x000000000041be9d:mov%rbx,-0x30(%rsp)
0x000000000041A2:mov%rbp,-0x28(%rsp)
0x000000000041A7:mov%r12,-0x20(%rsp)
0x000000000041beac:mov%r13,-0x18(%rsp)
0x000000000041beb1:mov%r14,-0x10(%rsp)
0x000000000041beb6:mov%r15,-0x8(%rsp)
0x000000000041bebb:sub$0x38,%rsp
0x000000000041bebf:mov$0x840,%edi
0x000000000041bec4:callq 0x402388
0x000000000041bec9:mov%rax,0x26e718(%rip)#0x68a5e8
0x000000000041bed0:mov$0x840,%r12d
0x000000000041bed6:测试%rax,%rax
0x000000000041bed9:je 0x41bf56
0x000000000041bedb:mov$0x0,%r13d
0x000000000041bee1:mov$0x0,%r14d
0x0000000000417:mov$0x0,%r15d
0x000000000041beed:mov%r13d,%edi
0x000000000041bef0:调用0x402578
更新

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时遇到过同样的问题?调试时经常发生这种情况

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


如果您仍然存在问题,请提供详细信息(编译器版本、脱胶机版本、平台和代码…

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

call _malloc
jz _failed
mov acc, _ngx_sys_errlist

现在在分配任务之前进行测试;您是否让源代码级别的跟踪向后移动以反映这一点?

不要使用goto。看在每个人的份上。你有一个调试器,看看生成的汇编代码。@Dani:对不起,这看起来像是对
goto
的完全有效的使用。我猜
failed
标签位于函数的底部(在正常的
返回之后),在一些清理代码之前。如果我是对的,那么这是一个非常适合
goto
的工作,其他任何事情都可能是一堆毫无意义的繁忙工作。@mu太短了:goto没有有效的用途。这只是一个剩余的语言,它是由C++语言构建的,它没有函数调用。@达尼:当你可以使用<代码>尝试< <代码> >代码> catch < /C>时,它不包括C(C等价的是代码> Goto < /COD>),或者嵌套函数<代码> SETJMP()>代码> /<代码> LojJMP(<代码> >,这使得<代码> Goto 看起来干净……还有一些嵌入式或受限上下文(例如,在中断的下半部分中正确使用它是很难做到的)。因为这是C代码(
malloc()
而不是
new[]
),所以您只能使用
goto
或更丑陋、逻辑混乱的机制,如伪循环。@geekosaur,请参阅我的更新,我认为它仍然存在:
je 0x41bf56
@compile fan:IIRC在x86上测试零的通常方法是使用
ing
%eax
本身,然后根据需要执行
je
jne
,因此您可能完全看到了我的建议。正如我们在汇编中看到的那样,它没有被优化。@geekosaur,我只是在谷歌上搜索了
测试%rax%rax
,似乎它也是检查
%rax
是否为
0
的有效方法。您可以检查这个答案:除了
%rax
是x86-64而不是x86之外,
test
在道德上与
相同。我认为哪一个更快取决于处理器的产生(过去几年生产的任何产品都可能更快;我不需要关心这个世纪:)。