有人能解释一下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
- 类型的变量,那么为什么它会显示value optimized out
?
我也无法设置found
的值。
这似乎是编译器优化(在这种情况下是-O2
);我怎样才能设置found
的价值?
答案 0 :(得分:113)
要调试优化代码,请学习汇编/机器语言。
使用GDB TUI模式。当我键入减号和Enter时,我的GDB副本启用它。然后键入C-x 2(按住Control并按X,释放两个然后按2)。这将把它放入拆分源和反汇编显示中。然后使用stepi
和nexti
一次移动一台机器指令。使用C-x o在TUI窗口之间切换。
下载有关CPU的机器语言和函数调用约定的PDF。您将很快学会识别函数参数和返回值的作用。
您可以使用GDB命令(如p $eax
答案 1 :(得分:74)
无需优化即可重新编译(gcc上为-O0)。
答案 2 :(得分:38)
将发现声明为“volatile”。这应该告诉编译器不要优化它。
volatile int found = 0;
答案 3 :(得分:11)
编译器将在启用优化的情况下开始执行非常聪明的操作。由于优化的方式变量存储在寄存器中,调试器将显示向前和向后跳跃的代码。这可能是您无法设置变量(或在某些情况下看到其值)的原因,因为它在寄存器之间巧妙地分配以提高速度,而不是具有调试器可以访问的直接存储器位置。
没有优化编译?
答案 4 :(得分:6)
通常,在像这样计算之后立即在分支中使用的布尔值实际上从不存储在变量中。相反,编译器只是直接分支从前面的比较中设置的condition codes。例如,
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”从未实际存储在任何地方。
答案 5 :(得分:4)
你几乎无法设置找到的值。调试优化程序很少值得麻烦,编译器可以重新排列代码,使其与源代码无关(除了产生相同的结果),从而使调试器混乱不堪。
答案 6 :(得分:4)
在调试优化程序时(如果在调试版本中没有显示错误,可能需要这样做),您通常必须了解生成的汇编编译器。
在您的特定情况下,cpnd_find_exact_ckptinfo
的返回值将存储在您的平台上用于返回值的寄存器中。在ix86
,即%eax
。在x86_64
:%rax
等。如果不是上述内容,您可能需要谷歌搜索“[您的处理器]程序调用约定”。
您可以在GDB
中检查该注册表,然后进行设置。例如。在ix86
:
(gdb) p $eax
(gdb) set $eax = 0
答案 7 :(得分:0)
我正在使用QtCreator和gdb。
添加
QMAKE_CXXFLAGS += -O0
QMAKE_CXXFLAGS -= -O1
QMAKE_CXXFLAGS -= -O2
QMAKE_CXXFLAGS -= -O3
适合我