Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does gdb show two different returns?

Tags:

c++

gdb

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
like image 899
YuppieNetworking Avatar asked May 10 '10 12:05

YuppieNetworking


2 Answers

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.

like image 98
crazyscot Avatar answered Oct 11 '22 23:10

crazyscot


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.

like image 21
unwind Avatar answered Oct 12 '22 01:10

unwind