C gdb通过指向错误的代码行显示错误的回溯跟踪

C gdb通过指向错误的代码行显示错误的回溯跟踪,c,gcc,optimization,gdb,abort,C,Gcc,Optimization,Gdb,Abort,通过在源代码中有多个中止调用,我们可以用非常简单的示例重现这个问题。在下面的示例代码中,我们在不同的条件下总共有四个中止调用,但是当我们使用优化标志(-O3)编译时,我们只能看到一个中止调用的调试信息。因此,在这四个中止调用中发生崩溃的地方,gdb总是给出一个包含调试信息的调用 #include <stdio.h> #include <stdlib.h> void level_aa(int a) { if (a == 0) abor

通过在源代码中有多个中止调用,我们可以用非常简单的示例重现这个问题。在下面的示例代码中,我们在不同的条件下总共有四个中止调用,但是当我们使用优化标志(-O3)编译时,我们只能看到一个中止调用的调试信息。因此,在这四个中止调用中发生崩溃的地方,gdb总是给出一个包含调试信息的调用

#include <stdio.h>
#include <stdlib.h>

void level_aa(int a)
{
        if (a == 0) 
          abort(); 
        if (a == 1) 
          abort();
        if (a == 2) 
          abort();

        abort();
}

int main(int argc,char *argv[])
{       int D;
        D = atoi(argv[1]);
        printf(" Value = %d", D);
        level_aa(D);
        return 0;
}
#包括
#包括
空层_aa(内部a)
{
如果(a==0)
中止();
如果(a==1)
中止();
如果(a==2)
中止();
中止();
}
int main(int argc,char*argv[])
{int D;
D=atoi(argv[1]);
printf(“值=%d”,d);
aa(D)级;
返回0;
}
将上面的代码与优化标志(-O3)混合,并使用gdb运行以重现问题

>gcc -g -O3 abort_crash.c -o abort
>gdb ./abort
(gdb)run 1
(gdb) bt
#0  0x00007ffff7ab2945 in *__GI_raise (sig=<optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#1  0x00007ffff7ab3f21 in *__GI_abort () at abort.c:92
#2  0x0000000000400634 in level_aa (a=<optimized out>) at abort_crash.c:13
#3  main (argc=<optimized out>, argv=<optimized out>) at abort_crash.c:20
(gdb) 
gcc-g-O3中止\u崩溃.c-o中止 >gdb./abort (gdb)运行1 (gdb)英国电信 #在../nptl/sysdeps/unix/sysv/linux/raise.c:64处0 0x00007ffff7ab2945 in*u GI_raise(sig=) #1 0x00007FF7AB3F21 in*\uuu GI\u abort()位于abort.c:92 #2 0x0000000000400634在中止时处于级别_aa(a=)c:13 #3主(argc=,argv=)在中止时崩溃。c:20 (gdb) 如果我们观察第2帧(#2),碰撞实际上发生在第9行,但gdb显示的是第13行。我可以理解,这是源代码优化的结果。 在这种情况下,有可能使gdb正常工作吗?(不进行优化) 提前感谢你的帮助

在这种情况下,有可能使gdb正常工作吗

在这种情况下,GDB工作得很好:它向您显示了实际发生的情况,即

(不进行优化)

。。。编译器发现多条路径导致
abort
函数无法返回且没有副作用,因此将这些路径合并在一起,减少了生成代码的大小。只需查看生成的程序集:

(gdb) disas level_aa
Dump of assembler code for function level_aa:
   0x0000000000400620 <+0>: sub    $0x8,%rsp
   0x0000000000400624 <+4>: callq  0x4004b0 <abort@plt>
End of assembler dump.
注意:需要
a+1
a+2
等来防止编译器合并单独的路径。如果您只调用了
my\u abort(a)
,编译器仍然可以将它们合并在一起,就像您编写了:

if (a >= 0 && a <= 2) my_abort(a);

如果(a>=0&&a不一定,你应该说waht是有这个问题的gdb的确切版本。同时也是gcc和binutils的确切版本。什么平台,在Linux的情况下是哪个发行版。我想知道如果(a>=0&&a感谢快速解决方案。感谢快速解决方案。不幸的是,我无法修改我们的源代码,因为这是一个非常大的项目。在这种情况下,如果我们有多个中止调用,我只想打印一条警告消息。因为问题只会出现在我们有多个中止调用的情况下。真的有可能知道是什么吗在使用优化时,我们只有一个或多个调用?提前感谢。有没有办法使用volatile来产生副作用,从而达到优化的目的,而不需要额外的代码?例如为自身分配局部变量。
if (a >= 0 && a <= 2) my_abort(a);