为什么GDB在行间跳转不可预知,并将variables打印为“<value optimized>”?

任何人都可以解释gdb的这种行为?

900 memset(&new_ckpt_info,'\0',sizeof(CKPT_INFO)); (gdb) **903 prev_offset = cp_node->offset;** (gdb) **905 m_CPND_CKPTINFO_READ(ckpt_info,(char *)cb->shm_addr.ckpt_addr+sizeof(CKPT_** HDR),i_offset); (gdb) **903 prev_offset = cp_node->offset;** (gdb) **905 m_CPND_CKPTINFO_READ(ckpt_info,(char *)cb->shm_addr.ckpt_addr+sizeof(CKPT_ HDR),i_offset);** (gdb) **908 bitmap_offset = client_hdl/32;** (gdb) **910 bitmap_value = cpnd_client_bitmap_set(client_hdl%32);** (gdb) **908 bitmap_offset = client_hdl/32;** (gdb) **910 bitmap_value = cpnd_client_bitmap_set(client_hdl%32);** (gdb) **908 bitmap_offset = client_hdl/32;** (gdb) **910 bitmap_value = cpnd_client_bitmap_set(client_hdl%32);** (gdb) 913 found = cpnd_find_exact_ckptinfo(cb , &ckpt_info , bitmap_offset , &offset , &prev_offset); (gdb) 916 if(!found) (gdb) p found $1 = <value optimized out> (gdb) set found=0 Left operand of assignment is not an lvalue. 

为什么在执行903行之后,它又为905 908 910执行相同的操作?

还有一件事情是found是一个bool型的variables,那么为什么它显示value optimized out呢? 我也无法设置found的值。

这似乎是一个编译器优化(在这种情况下它的-O2 ); 我怎么还能设置found的值?

debugging优化的代码,学习汇编/机器语言。

使用GDB TUI模式。 当我input减号和回车时,我的GDB副本可以启用它。 然后键入Cx 2(即按住Control并按下X,释放两者,然后按下2)。 这将把它分解源和反汇编显示。 然后使用stepinexti移动一条机器指令。 使用Cx o在TUI窗口之间切换。

下载关于您的CPU的机器语言和函数调用约定的PDF。 您将快速学会识别正在执行的函数参数和返回值。

您可以使用像p $eax这样的GDB命令来显示寄存器的值

无需优化重新编译(gcc上的-O0)。

声明为“volatile”。 这应该告诉编译器不要优化它。

 volatile int found = 0; 

编译器将开始做非常聪明的事情打开优化。 debugging器将显示代码向前和向后跳跃,因为优化的方式variables存储在寄存器中。 这可能是你不能设置你的variables(或者在某些情况下看到它的值)的原因,因为它已经在寄存器之间巧妙地分配了速度,而不是debugging器可以访问的直接内存位置。

编译没有优化?

通常情况下,像这样计算后立即在分支中使用的布尔值实际上并不存储在variables中。 相反,编译器只是直接从前面的比较中设置的条件代码分支出来。 例如,

 int a = SomeFunction(); bool result = --a >= 0; // use subtraction as example computation if ( result ) { foo(); } else { bar(); } return; 

通常编译为如下所示:

 call .SomeFunction ; calls to SomeFunction(), which stores its return value in eax sub eax, 1 ; subtract 1 from eax and store in eax, set S (sign) flag if result is negative jl ELSEBLOCK ; GOTO label "ELSEBLOCK" if S flag is set call .foo ; this is the "if" black, call foo() j FINISH ; GOTO FINISH; skip over the "else" block ELSEBLOCK: ; label this location to the assembler call .bar FINISH: ; both paths end up here ret ; return 

注意“bool”从来没有真正存储在任何地方。

你几乎不能设置find的值。 debugging优化后的程序很less会遇到麻烦,编译器可以按照与源代码无关的方式重新排列代码(除了产生相同的结果),从而使debugging器混淆不清。

当debugging优化的程序(如果错误没有显示在debugging版本中,这可能是必要的),您通常必须了解生成的汇编编译器。

在您的具体情况下, cpnd_find_exact_ckptinfo返回值将被存储在您的平台上用于返回值的寄存器中。 在ix86 ,这将是%eax 。 在x86_64%rax ,等等。如果不是上面所说的,你可能需要谷歌来处理'[你的处理器]过程调用约定'。

你可以在GDB检查那个寄存器,你可以设置它。 例如在ix86

 (gdb) p $eax (gdb) set $eax = 0 

即时通讯与gdb使用QtCreator。

添加

 QMAKE_CXXFLAGS += -O0 QMAKE_CXXFLAGS -= -O1 QMAKE_CXXFLAGS -= -O2 QMAKE_CXXFLAGS -= -O3 

适合我