When debugging a program that fails an assert I can't get the call stack in gdb. I'm using g++4.8 and gdb from Homebrew on Mavericks.
/usr/local/bin/g++-4.8 --version
g++-4.8 (GCC) 4.8.2
/usr/local/bin/gdb --version
GNU gdb (GDB) 7.6.2
Here is the smallest test to reconstruct the problem
//test.cpp
#include <iostream>
#include <cassert>
int main()
{
int i = 42;
std::cout << "Hello World!" << i << std::endl;
assert(0); // this also happens with abort() which assert(0) winds up calling
}
Compiling and with
/usr/local/bin/g++-4.8 -g -c test.cpp -o test.o
/usr/local/bin/g++-4.8 -g test.o -o test
/usr/local/bin/gdb test
(gdb) r
Starting program: /Users/pmelsted/tmp/test/test
Hello World!42
Assertion failed: (0), function main, file test.cpp, line 7.
Program received signal SIGABRT, Aborted.
0x00007fff9447d866 in ?? ()
(gdb) where
#0 0x00007fff9447d866 in ?? ()
#1 0x00007fff9229835c in ?? ()
#2 0x0000000000000000 in ?? ()
A common example of when we would need to navigate the call stack within GDB is if execution stops within library code. We can use, the where, up and frame commands to inspect variables within code that we wrote. It is assumed that you have the knowledge introduced in the Basic Use, Breakpoints, Viewing Data and Execution modules.
Stack frames are regions of memory allocated on the stack to hold the local variables of functions each time they are called. When one function calls another, a new stack frame is allocated and placed on top of the current function’s stack frame. When a function returns, its stack frame is de-allocated.
Able to view and traverse the function call stack using the where, up, down and frame commands. In order to debug programs with functions (i.e. most programs), it is helpful to inspect the variables of all functions in the current call stack, i.e. the functions called to get to the current point in the program.
It seems gdb on MacOS don't display call stack correctly (or call stack is corrupted after assert() function call) for 64-bit programs. Here is the program slightly modified:
//test.cpp
#include <iostream>
#include <cassert>
int foo() {
assert(0);
}
int bar() {
return foo();
}
int main()
{
int i = 42;
std::cout << "Hello World!" << i << std::endl;
return bar();
}
I have compiled it invoking the g++ -g 15.cpp -m32 command and have ran it under ggdb. The bt full command shows call stack as the following:
(gdb) bt full
#0 0x9843f952 in ?? ()
No symbol table info available.
#1 0x96193340 in ?? ()
No symbol table info available.
#2 0x9615e43e in ?? ()
No symbol table info available.
#3 0x0000216f in foo () at 15.cpp:6
No locals.
#4 0x0000217b in bar () at 15.cpp:9
No locals.
#5 0x000021e4 in main () at 15.cpp:15
i = 42
(gdb) quit
So, all debug symbols are displayed correctly, first 3 function addresses are corrected and have no name because my libgcc is in release mode.
If I don't use -m32 key during compilation, the call stack is as follows:
(gdb) bt full
#0 0x00007fff8b442866 in ?? ()
No symbol table info available.
#1 0x00007fff8c64735c in ?? ()
No symbol table info available.
#2 0x0000000000000000 in ?? ()
No symbol table info available.
That is definitely wrong call stack, #2 frame function address is 0x0. So, the root cause is gdb can't display call stack correctly for 64-bit applications.
I found a workaround for the problem. Just set the breakpoint to abort() function in gdb:
b abort
then when assert is called it will halt at the breakpoint and at this moment one can see the call stack with bt
.
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