Why does gdb show two different returns? - c++

Last week I was a debugging a code and a weird situation came up: gdb passes through two different return clauses. I made a simple example that illustrates the situation:
#include <iostream>
using namespace std;
int test() {
string a = "asd";
string b = "asd";
while (true) {
if (a == b) {
return 0;
}
}
return -1;
}
int main() {
int result = test();
cout << "result: " << result << endl;
}
When debugging the code I got:
(gdb) b main
Breakpoint 1 at 0x1d4c: file example.cpp, line 19.
(gdb) r
Starting program: /Users/yuppienet/temp/a.out
Reading symbols for shared libraries +++. done
Breakpoint 1, main () at example.cpp:19
19 int result = test();
(gdb) s
test () at example.cpp:7
7 string a = "asd";
(gdb) n
8 string b = "asd";
(gdb) n
11 if (a == b) {
(gdb) n
12 return 0;
(gdb) n
15 return -1;
(gdb) n
16 }
(gdb) n
main () at example.cpp:20
20 cout << "result: " << result << endl;
(gdb) n
result: 0
21 }
(gdb) n
0x00001ab2 in start ()
I noted that even if gdb shows line 15, the return value is 0 (the finish command confirms this as well).
So the question is: why does gdb show line 15: return -1, even if the function is not really returning this value?
Thanks!
Edit:
I forgot to mention that I compiled with the following line:
g++ -Wall -pedantic -g -pg example.cpp

I suspect you're seeing the function epilogue. Your two strings have destructors, which are being implicitly called on return. Check out what the disassembly says to be sure, but I suspect that both return statements are mapping to something along the lines of:
stash return_value;
goto epilogue;
and correspondingly:
epilogue:
destroy a; // on the stack, so destructor will be called
destroy b;
really_return(stashed value);
The epilogue appears to come from line 15 as a side-effect of how g++ does line numbering - a fairly simple format, really just a list of tags of the form "address X comes from line number Y" - and so it's reporting 15 as the closest match. Confusing in this case, but correct a lot of the time.

Probably because the program counter register passes through the instructions that best map to the final return, i.e. the function's exit sequence. The actual return value is probably kept in a register, so the first return just loads the proper value and jumps to the end of the function, and then that address is "back-mapped" to the source code line of the final return.

You don't say, but if you compiled with optimization that is exactly the kind of behavior you would see in gdb. You see the first line setting up the return value, and then it jumps to the real return instruction but in C++ you see the entire thing including the return value.

Related

Printing structure varibales at a particular point

Lets say we have a structure with some variables.
Is it possible to values of those variables at a particular point of execution..?
One way might be to print each of them individually.
But my point is, is there a way to check values of all the variables in that structure at a particular point of time, without having to use printf or cout to print each variable value..?
Just wondering if this is possible atleast in gdb..!!
it is possible in gdb, no problem:
For example:
x.C
#include <iostream>
struct A {
int x;
int y;
};
int main(int argc,char **argv) {
A a;
a.x=10;
a.y=11;
std::cout << "Hello world" << std::endl;
}
compiling:
g++ -g -o x x.C
running on gdb
gdb x
(gdb) break main
Breakpoint 1 at 0x40096c: file x.C, line 10.
(gdb) run
Starting program: /home/jsantand/x
Breakpoint 1, main (argc=1, argv=0x7fffffffde98) at x.C:10
10 a.x=10;
(gdb) next
11 a.y=11;
(gdb) next
12 std::cout << "Hello world" << std::endl;
(gdb) print a
$1 = {x = 10, y = 11}
(gdb) quit
Doing that on your code, traces, etc... it will be be more difficult as C++ lacks reflection.
You could do it by hand or if you're adventurous, create something to generate automatically operator<< for your classes an structs/classes so that they provide a string representation. You need some basic C++ parser at least.

View print methods in GDB

I have a complicated class for which I have written a clean printing method, more-or-less explicitly for the purposes of debugging. However, I can't seem to figure out the syntax to actually use it to print when I'm using gdb. Basically I want to be able to type something like "myObject->print()" and have it run my print method but instead I get the following error:
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x00000000000000a1
0x00007fff814c0684 in std::ostream::sentry::sentry () The program
being debugged was signaled while in a function called from GDB. GDB
remains in the frame where the signal was received. To change this
behavior use "set unwindonsignal on" Evaluation of the expression
containing the function (wfSamplePath::print_traj(std::ostream&)) will
be abandoned.
where "wfSamplePath" is my class and "print_traj" is my print method (with std::cout as the default argument). So clearly something is wrong with how I think I can do this. I'm using gdb from within xcode 3. "myObject" is definitely in scope, as I can access some of its other methods.
The expression evaluator in GDB is quite limited, particularly with C++ expressions, so try to keep it simple. Particularly, do not use default arguments. Using cout is also probably a bad idea. So are inline functions.
I've got good results with a simple member function that returns a string. For example this code works as expected:
#include <sstream>
struct S
{
int x, y, z;
std::string debug();
};
std::string S::debug()
{
std::ostringstream os;
os << x << ", " << y << ", " << z;
return os.str();
}
int main()
{
S s;
s.x = 1;
s.y = 2;
s.z = 3;
return 0;
}
Then, compile and debug with:
$ g++ -O0 -g test.cpp
$ gdb ./a.out
....
$start
....
19 s.x = 1;
(gdb) n
20 s.y = 2;
(gdb) n
21 s.z = 3;
(gdb) n
22 return 0;
(gdb) p s.debug()
$1 = "1, 2, 3"

C++ gdb print array gives No symbol "d" in context

I am trying to debug a C++ program but I face the below issue when trying to print the contents of the array.
I have declared a array of chars as below in the c++ program
using namespace std;
int main() {
string s;
cin >> s;
char d[s.size()];
int i=0;
int j=0;
while(j<s.size()) {
if(s[j] != '+') {
d[i++] = s[j];
}
j++;
}
}
I use the below commands to compile the above code and run gdb
g++ -g main.cpp -o main
gdb main
However when I debug and hit the below command in GDB I get the below error.
Command entered in GDB : p *d#10
No symbol "d" in current context.
Can you please let me know what I can do so that all the contents of the array is printed?
Until you run the program, there are no variables to print. For your program, you should set a breakpoint at the last line of main, and run the program. When the program stops at the breakpoint, you can then print d.
(gdb) list 15
10 while(j<s.size()) {
11 if(s[j] != '+') {
12 d[i++] = s[j];
13 }
14 j++;
15 }
16 }
(gdb) break 15
Breakpoint 1 at 0x80488b9: file x.cc, line 15.
(gdb) run
Starting program: /home/jxh/StackOverflow/gdb/a.out
1234567890
Breakpoint 1, main () at x.cc:15
15 }
(gdb) p *d#10
$2 = "1234567890"
(gdb)
Make sure to turn off compiler optimizations. This link gives a little more detail.

why does inferior exit "normally" when i use dprintf in gdb?

I'm running a very trivial program (just a main with some random int assignments) to test out dprintf from gdb. A main which looks like this:
int main(void)
{
int h = 17;
int k = 42;
std::cout << "stop here" << std::endl;
}
(the h part is line 5). I set the dprintf 6,"h is %d\n",h and if i say start I am taken to line 5 as expected..if I then say advance 7 the program exits even though 7 is the std::cout - why is this? (if I don't use dprintf and I say advance 7 I do, indeed, break on the std::cout line..)
why is this?
It's a bug in GDB. You can report it in GDB bugzilla.

conditional display in gdb

I'm using gdb to debug some c++ code. At the moment the code I'm looking at iterates through an array of pointers, which are either a pointer to some object or a NULL pointer.
If I just display list[index]->member it'll complain when list[index] is null. Is there anyway to display the member only if list[index] is not null? I know you can set conditional breakpoints (condition <bp-num> <exp>) but I'm not sure how that'd help.
The code in question is:
for (int i=0;i<BSIZE*BSIZE;i++){
if (vms[i]==target) {valid=true; break;}
}
where vms is the array of pointers.
Since display accepts arbitrary expressions, you can try something like the following display command:
display (list[index]) ? list[index]->member : "null"
I'm not sure if that cleans things up well enough for what you want - you'll still get a display, but it won't be a complaint.
Basically the condition works like this:
#include <iostream>
int main() {
for (int i=0; i<10; ++i) {
std::cerr << i << std::endl;
}
}
You can debug it like this:
(gdb) break 5
Breakpoint 1 at 0x100000d0e: file foobar.cpp, line 5.
(gdb) condition 1 i==3
(gdb) r
Starting program: /private/tmp/foobar
Reading symbols for shared libraries ++. done
0
1
2
Breakpoint 1, main () at foobar.cpp:5
5 std::cerr << i << std::endl;