88

Can anyone explain this behavior of 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.

Why after executing line 903 it again executes the same for 905 908 910?

Another things is found is a bool-type variable, so why it is showing value optimized out? I am not able to set the value of found as well.

This seems to be a compiler optimization (in this case its -O2); how can I still set the value of found?

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
Arpit
  • 4,259
  • 10
  • 38
  • 43
  • 9
    when debugging, it's generally a good idea to compile with -O0 as optimizing leads to that kind of problems. – LiraNuna Aug 28 '09 at 08:35

8 Answers8

115

To debug optimized code, learn assembly/machine language.

Use the GDB TUI mode. My copy of GDB enables it when I type the minus and Enter. Then type C-x 2 (that is hold down Control and press X, release both and then press 2). That will put it into split source and disassembly display. Then use stepi and nexti to move one machine instruction at a time. Use C-x o to switch between the TUI windows.

Download a PDF about your CPU's machine language and the function calling conventions. You will quickly learn to recognize what is being done with function arguments and return values.

You can display the value of a register by using a GDB command like p $eax

Zan Lynx
  • 53,022
  • 10
  • 79
  • 131
  • I still have the "optimized out" problem, and the variable value is not shown in the other windows, but, still, it's a great information, thanks! – The Student Feb 05 '13 at 12:29
  • 17
    @TomBrito: Optimized out means the variable isn't in memory. It is probably in a CPU register only, which means that you need to read the disassembly and print the register values in order to find it. – Zan Lynx Feb 05 '13 at 17:25
  • @Zan Lynx: I'm not sure I agree with your analysis. DWARF symbols have enough info to extract values from registers. Perhaps what's meant here is that the compiler has determined that the variable can be safely discarded by the time execution reaches the current line. In that case the storage where the variable lives has probably been reused for something else. I think you're correct that this would normally only happen if the variable was enregistered, though. – Ian Ni-Lewis Sep 03 '14 at 22:38
  • @IanNi-Lewis: I don't know what version of DWARF you're using but in my experience GDB cannot print a variable that has been stored into a register. – Zan Lynx Sep 03 '14 at 22:40
  • I'm sure you're right. My experience with DWARF comes from writing my own parser, not from using gdb, so I don't really know what gdb is capable of. – Ian Ni-Lewis Feb 03 '15 at 15:51
  • You can use `gdbtui` to save you typing `C-x 2` :-). Thanks for a tip :-). – pevik Jun 15 '16 at 22:24
  • What about compile with `-g3` ? – Kyrol Jun 23 '16 at 14:19
  • @IanNi-Lewis this is most likely the result of GCC not emitting symbols for register-only variables. – Ruslan Oct 23 '16 at 14:07
76

Recompile without optimizations (-O0 on gcc).

D'Nabre
  • 2,226
  • 16
  • 13
  • 18
    Even -O0 can produce optimized out code (trying to struggle with this right now), although I'm not sure why. – Chris Gregg Apr 22 '15 at 13:37
  • @ChrisGregg I got the same problem! Have you find out what is the issue? – Paolo M Apr 27 '15 at 07:28
  • 1
    @paolom it looks like it might be a clang issue, so I have been compiling with g++ instead for debugging purposes, unfortunately. – Chris Gregg Apr 28 '15 at 08:48
  • Often this isn't a solution - especially if you have a core dump from production and/or you are unable to reproduce the problem on development environment. – smbear Nov 16 '17 at 10:43
40

Declare found as "volatile". This should tell the compiler to NOT optimize it out.

volatile int found = 0;
BenB
  • 10,300
  • 7
  • 32
  • 30
  • 1
    Even when I declare some variables "volatile" in the gdb debugger it shows it as optimized out variable! Is there anymore into this? – M.Rez Aug 08 '16 at 08:16
12

The compiler will start doing very clever things with optimisations turned on. The debugger will show the code jumping forward and backwards alot due to the optimized way variables are stored in registers. This is probably the reason why you can't set your variable (or in some cases see its value) as it has been cleverly distributed between registers for speed, rather than having a direct memory location that the debugger can access.

Compile without optimisations?

kjfletch
  • 5,394
  • 3
  • 32
  • 38
6

You pretty much can't set the value of found. Debugging optimized programs is rarely worth the trouble, the compiler can rearrange the code in ways that it'll in no way correspond to the source code (other than producing the same result), thus confusing debuggers to no end.

nos
  • 223,662
  • 58
  • 417
  • 506
6

Typically, boolean values that are used in branches immediately after they're calculated like this are never actually stored in variables. Instead, the compiler just branches directly off the condition codes that were set from the preceding comparison. For example,

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

Usually compiles to something like:

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

Notice how the "bool" is never actually stored anywhere.

Crashworks
  • 40,496
  • 12
  • 101
  • 170
5

When debugging optimized programs (which may be necessary if the bug doesn't show up in debug builds), you often have to understand assembly compiler generated.

In your particular case, return value of cpnd_find_exact_ckptinfo will be stored in the register which is used on your platform for return values. On ix86, that would be %eax. On x86_64: %rax, etc. You may need to google for '[your processor] procedure calling convention' if it's none of the above.

You can examine that register in GDB and you can set it. E.g. on ix86:

(gdb) p $eax
(gdb) set $eax = 0 
Employed Russian
  • 199,314
  • 34
  • 295
  • 362
0

Im using QtCreator with gdb.

Adding

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

Works well for me

Haselnussstrauch
  • 333
  • 2
  • 10