In gdb how can I discover the value of a variable which displays as optimized out? Presumably the value is being stored in a register, how can I find out which one? Given this simple program (copied from the website named below).
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int foo = rand();
printf("foo is %d\n", foo++);
return foo;
}
Compile with optimization.
gcc -O3 -g optimized.c
gdb a.out
Run GDB
(gdb) print foo
$1 = <optimized out>
What is going on? The variable foo
must exist somewhere but how do I find its value or where it is stored?
I found a page which explains in detail how the DWARF debug information works for optimized code https://undo.io/resources/gdb-watchpoint/build-for-debug-in-gdb. Using the suggestions there I could eventually find the register assigned to foo
but it's rather painful.
How can I get gdb to tell me which register to watch?
I tried compiling with -g3 but that didn't help.
I tried a few commands in gdb which also didn't help.
ptype foo
info locals
print &foo
The variable foo must exist somewhere
There is no requirement that it should exist. C++ operates on the as-if principle. The program works as if the variable exists. If the compiler can get away with throwing your variable out of the window, while adhering to the as-if principle, expect it to do so eagerly. This is the very essence of optimisation. If you don't like it, don't use optimisation. For extra double strong protection, declare the variable of interest volatile
.
how do I find its value or where it is stored
It does not have to be stored anywhere. In this case you can find its value by looking at the output of the program and/or examining its exit status. There is no general method to deternine which register an optimised-out variable gets assigned. There may or may not be such a register, depending on the exact details of your program. The value and the computation that leads to it might well be optimised away together with the storage. (Not in this case because the value is visible from the outside).
The variable foo must exist somewhere
Not necessarily. The compiler may instead store some value derived from the variable (e.g. foo+1
or foo-23
) if it's convenient.
In this particular case, since foo
is being passed to printf
, you can discover it in a register or on the stack if you know the calling convention for your particular platform.
but how do I find its value or where it is stored?
Debugging optimized code currently requires significant skill, knowledge of the ABI and the assembly instructions used.
The problem is that compilers rarely accurately track values through their in-register and in-memory locations for debugging purposes, because doing so is quite hard.
Debuggers also have to correctly interpret the debugging info which compilers produce, and that isn't an easy or bug-free process either.
GCC recently had a lot of improvement in that area. Using gcc (GCC) 9.2.1 20190827 (Red Hat 9.2.1-1)
from Fedora 31 on Linux x86_64, I observe this:
(gdb) start
Temporary breakpoint 1 at 0x401050: file t.c, line 6.
Starting program: /tmp/a.out
Missing separate debuginfos, use: dnf debuginfo-install glibc-2.30-5.fc31.x86_64
Temporary breakpoint 1, main () at t.c:6
6 int foo = rand();
(gdb) n
7 printf("foo is %d\n", foo++);
(gdb) p foo
$1 = 1804289384
(gdb) p &foo
Can't take address of "foo" which isn't an lvalue.
(gdb) c
Continuing.
foo is 1804289383
[Inferior 1 (process 2696) exited with code 0150]
(gdb) q
Here you can see that gcc
described the location of foo
in a register (or some other location that isn't memory), and GDB was able to print almost the value of foo
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With