GDB: breakpoint when calling destructor of specific object - c++

In my app, I'm getting a SIGSEGV fault after trying to access a field inside a widget pointer. That widget comes from a 3rd-party library. I know exactly the point where the signal is being thrown. What I want to know, is if in that specific moment, the "this" pointer of the faulty widget has been deleted or not, and when that happened.
So, the idea is to set a breakpoint at a place where I know my object does exist, and, and here is where my question borns, say to gdb: "break when the destructor of this specific "this" pointer is called". How can I tell gdb to do that?
In such a case, a can know if the object is deleted before the signal is thrown, and where and why that object has been deleted (to fix the situation).

How can I tell gdb to do that?
Use conditional breakpoint. Example:
cat -n t.cc
1 struct Foo {
2 ~Foo() {}
3 };
4
5 Foo *af1, *af2;
6 int main()
7 {
8 Foo f1;
9 af1 = &f1;
10 {
11 Foo f2;
12 af2 = &f2;
13 }
14 }
g++ -g t.cc && gdb -q ./a.out
(gdb) b 12
Breakpoint 1 at 0x400500: file t.cc, line 12.
(gdb) r
Starting program: /tmp/a.out
Breakpoint 1, main () at t.cc:12
12 af2 = &f2;
(gdb) p &f2
$1 = (Foo *) 0x7fffffffdc9f
(gdb) p &f1
$2 = (Foo *) 0x7fffffffdc9e
(gdb) b 'Foo::~Foo()' if this == 0x7fffffffdc9f
Breakpoint 2 at 0x400532: file t.cc, line 2.
(gdb) c
Continuing.
Breakpoint 2, Foo::~Foo (this=0x7fffffffdc9f, __in_chrg=<optimized out>) at t.cc:2
2 ~Foo() {}
(gdb) bt
#0 Foo::~Foo (this=0x7fffffffdc9f, __in_chrg=<optimized out>) at t.cc:2
#1 0x0000000000400517 in main () at t.cc:12
(gdb) c
Continuing.
[Inferior 1 (process 121877) exited normally]
Voila: breakpoint was hit when f2 was destructed, but not when f1 was.

Related

can gdb show the variable being destructed?

Example:
#include <assert.h>
int v = 0;
struct Foo {
Foo() { ++v; }
~Foo()
{
--v;
assert(v != 1); // artificially stop the debugger here
}
};
int main()
{
Foo a; // assert in destructor here?
Foo b; // assert in destructor here?
Foo c; // assert in destructor here?
return 0;
} // main()
This code asserts. I think the debugger should be able to tell me which line/instance of Foo is asserting, but it only shows that it's exiting the scope of main():
#6 0x00007ffff7d9ee96 in __GI___assert_fail (assertion=0x555555556019 "v != 1", file=0x555555556010 "main.cpp", line=8,
function=0x555555556004 "Foo::~Foo()") at ./assert/assert.c:101
#7 0x000055555555521c in Foo::~Foo (this=<optimized out>, __in_chrg=<optimized out>) at main.cpp:8
#8 0x00005555555551b6 in main () at main.cpp:17
(gdb) f 8
#8 0x00005555555551b6 in main () at main.cpp:17
17 } // main()
I know the culprit is b, but how can I make gcc tell me?
Is this just a missing feature or is there somethig more fundamental preventing debuggers from showing this information?
If I add a scope for each instance it becomes clear, but I don't think I should have to recompile.
int main()
{
Foo a;
{
Foo b;
{
Foo c;
}
} // <-- backtrace of the assert shows this line
return 0;
}
The same problem exists for members of a class:
class Bar {
Foo a;
Foo b;
Foo c;
};
[EDIT] What I'd really like to see is the debugger stepping back to the line with Foo c; when it returns from main(), then Foo b; etc. Just like what happens in the following example, where the debugger steps through the Baz() lines one at a time before finally entering func().
func(Baz(),
Baz(),
Baz());
but how can I make gcc tell me?
You can't (at least not directly) -- it has no idea that you are interested in this. But you can give each instance of Foo a name it to print the value of this and the name in both constructor and destructor.
You could also get this info from GDB:
Program received signal SIGABRT, Aborted.
__pthread_kill_implementation (threadid=<optimized out>, signo=6, no_tid=no_tid#entry=0) at ./nptl/pthread_kill.c:44
44 ./nptl/pthread_kill.c: No such file or directory.
(gdb) bt
#0 __pthread_kill_implementation (threadid=<optimized out>, signo=6, no_tid=no_tid#entry=0) at ./nptl/pthread_kill.c:44
#1 0x00007ffff7e55d2f in __pthread_kill_internal (signo=<optimized out>, threadid=<optimized out>) at ./nptl/pthread_kill.c:89
#2 __GI___pthread_kill (threadid=<optimized out>, signo=<optimized out>) at ./nptl/pthread_kill.c:89
#3 0x00007ffff7f9ee70 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#4 0x00007ffff7df1472 in __GI_abort () at ./stdlib/abort.c:79
#5 0x00007ffff7df1395 in __assert_fail_base (fmt=<optimized out>, assertion=<optimized out>, file=<optimized out>, line=<optimized out>, function=<optimized out>) at ./assert/assert.c:92
#6 0x00007ffff7dffdf2 in __GI___assert_fail (assertion=0x555555556015 "v != 1", file=0x555555556010 "t.cc", line=10, function=0x555555556004 "Foo::~Foo()") at ./assert/assert.c:101
#7 0x0000555555555200 in Foo::~Foo (this=0x7fffffffd81e, __in_chrg=<optimized out>) at t.cc:10
#8 0x0000555555555183 in main () at t.cc:20
(gdb) fr 8
#8 0x0000555555555183 in main () at t.cc:20
20 } // main()
(gdb) info locals
a = {<No data fields>}
b = {<No data fields>}
c = {<No data fields>}
(gdb) p &a
$1 = (Foo *) 0x7fffffffd81f
(gdb) p &b
$2 = (Foo *) 0x7fffffffd81e <<=== match for this in frame 7
This of course requires that this isn't optimized (as it is in your stack), or that you print the value of this in the destructor.
[EDIT] What I'd really like to see is the debugger stepping back to the line with Foo c; when it returns from main(), then Foo b; etc.
A compiler could in theory do that, but (I suspect) this will be exceedingly confusing to most end-users: "why is the destructor being invoked when I am simply constructing Foo?".

How to debug a function with gdb

Using gdb, I can put a breakpoint anywhere a function is called, and step through the function evaluation. I can also evaluate a function with the print command. When stopped at any breakpoint, I would like to debug a specific function by stepping through its execution using different arguments. However, when I try to set a breakpoint at the function and give gdb a suitable print command, gdb objects with the message "The program being debugged stopped while in a function called by gdb. Evaluation of the expression containing the function MyClass::mysize(int,int) will be abandoned". Is there any way to accomplish this without restarting the program?
You managed to miss part of the message from GDB. Here is my sample program:
int
foo (int arg)
{
return arg + 3;
}
int
main ()
{
return foo (-3);
}
And here is my GDB session:
(gdb) start
Temporary breakpoint 1 at 0x401119: file eval.c, line 10.
Starting program: eval.x
Temporary breakpoint 1, main () at eval.c:10
10 return foo (-3);
(gdb) break foo
Breakpoint 2 at 0x40110d: file eval.c, line 4.
(gdb) print foo (2)
Breakpoint 2, foo (arg=2) at eval.c:4
4 return arg + 3;
The program being debugged stopped while in a function called from GDB.
Evaluation of the expression containing the function
(foo) will be abandoned.
When the function is done executing, GDB will silently stop.
(gdb) bt
#0 foo (arg=2) at eval.c:4
#1 <function called from gdb>
#2 main () at eval.c:10
(gdb)
Notice the last line of the message from GDB: When the function is done executing, GDB will silently stop. So GDB is still inside the called function with the arguments you passed. The can be seen in the backtrace with <function called from GDB>.
So you can continue stepping through the function to see how it behaves. What you don't get is the printing of the result when the function returns, GDB has lost track of the fact that this is what you wanted, so instead, when the function returns GDB will just drop you back to the prompt. What this means is that you should inspect the return value inside the function before it returns.

Pthread_create seems to flush the argument passed to the input function

I am working on a pthread code to do repeated matrix vector product. While doing so, I first wrote the serial matrix vector code for multiplication and then later I attempted to put the matrix vector product into separate threads.
The code https://github.com/viswans/parallel-computing-cs525/blob/pthread/pthread_page_rank/src/pthread/pagerankPthread.cpp does what I just described. Particularly when the number of threads is increased from 8 to 9, the binary results in a segmentation fault.
On debugging using gdb I noticed that there was a null pointer being dereferenced, and I added a watch point on that pointer to see if it is being set properly. What I noticed was that the argument to the function being called from pthread_create seems to be flushed and set to 0!
Old value = 37843
New value = 45242576
0x0000000000403436 in __gnu_cxx::new_allocator<(anonymous namespace)::ThreadStruct>::construct<(anonymous namespace)::ThreadStruct, (anonymous namespace)::ThreadStruct> (this=0x2b25970, __p=0x2b260e0) at /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.4/include/g++-v4/ext/new_allocator.h:120
120 { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
(gdb) c
Continuing.
[New Thread 0x7ffff2985700 (LWP 3390)]
[New Thread 0x7ffff2184700 (LWP 3391)]
[New Thread 0x7ffff1983700 (LWP 3392)]
[New Thread 0x7ffff1182700 (LWP 3393)]
Hardware watchpoint 3: *(0x2b260e8)
Old value = 45242576
New value = 0
0x00007ffff708eedb in __memset_sse2 () from /lib64/libc.so.6
(gdb) bt
#0 0x00007ffff708eedb in __memset_sse2 () from /lib64/libc.so.6
#1 0x00007ffff7ded2e2 in allocate_dtv () from /lib64/ld-linux-x86-64.so.2
#2 0x00007ffff7ded9be in _dl_allocate_tls () from /lib64/ld-linux-x86-64.so.2
#3 0x00007ffff7bc9fc5 in pthread_create##GLIBC_2.2.5 () from /lib64/libpthread.so.0
#4 0x0000000000402b47 in PageRank::PageRankPthread::calculatePageRank (matrix=std::shared_ptr (count 1, weak 0) 0x2b258d0,�
input=std::vector of length 196591, capacity 196591 = {...}, num_threads=9, criterion=...) at src/pthread/pagerankPthread.cpp:84
#5 0x0000000000401d5d in mainPthread (argc=3, argv=0x7fffffffe6b8) at src/pthread/mainPthread.cpp:31
#6 0x000000000040be47 in main (argc=3, argv=0x7fffffffe6b8) at src/main.cpp:9
Any insight about why pthread_create would flush the arguments would be much appreciated.
Thanks
Sudharshan
You call push_back on the tstruct vector, which invalidates all pointers into that vector, causing the threads to access structures that have moved. One simple fix is to add tstruct.reserve(num_threads); after std::vector< ThreadStruct > tstruct;.
But you should really rethink this and do things in a more sensible way. Is a vector of structures a suitable collection to use when you need a pointer into the collection to remain valid as the collection is modified?

How to break at a constructor of base class using gdb?

My main cpp file is as:
class UnifiedDirListQuery : public UnifiedQuery{
public:
UnifiedDirListQuery(){
//do something-------------line 12
}
}
//other code
int main( void ){
UnifiedQuery *query = new UnifiedDirListQuery();//-----line 56
//do something
delete query;
}
And the UnifiedQuery is declared and defined in unified.h and unified.cpp respectively. When I debug this program in gdb:
gdb: b 56
gdb: r
gdb: s
the program jumped to line 12. How to go to unified.cpp and jump to the Ctor of base class UnifiedQuery if the ctor is defined in unified.cpp : line 25 for instance.
UPDATES
For the answer break UnifiedDirListQuery::UnifiedDirListQuery the gdb complains that:
(gdb) b UnifiedDirListQuery::UnifiedDirListQuery
[0] cancel
[1] all
?HERE
?HERE
> 1
Note: breakpoint -1 (disabled) also set at pc 0x0.
Breakpoint 1 at 0x0
Note: breakpoints -1 (disabled) and 1 also set at pc 0x0.
Breakpoint 2 at 0x0
warning: Multiple breakpoints were set.
Use the "delete" command to delete unwanted breakpoints.
(gdb) r
Starting program: /...(the path)/src/base/unified_album_list.cgi
Warning:
Cannot insert breakpoint 1.
Error accessing memory address 0x0: Input/output error.
For the answer b file:line, gdb just ignore it and went through the program without stop. BTW: actually the definition of the ctor is in a file named unified.h, implicity declared as an inline function since it is in a header file.
You can also
break UnifiedDirListQuery::UnifiedDirListQuery
Notice also that gdb has tab completion, so you don't have to type everything.
break unified.cpp:25 should do the trick, to break at line 25 for example
Especially if you have more than one file, you must give the name of the file where you want to break. See here for more information

Switching between multiple stacks in gdb 6.3

There are two stacks in the program: one is created by OS and the second is created by program itself to run some code with it.
When the program crashes in the second stack, I want to switch to the main stack in gdb and see the backtrace. Is it possible?
I tried to save the rsp to a variable and change it after the crash, but the resulting backtrace was not right. I think gdb cannot differentiate frames in stack.
I think you were right with the approach of just restoring some register values to point GDB at the right stack. It's difficult to know how your application may have worked without any of its source, but for the very simple make/swapcontext application below:
#include <stdio.h>
#include <ucontext.h>
#include <unistd.h>
ucontext_t a_ctx, b_ctx;
char b_stack[4096];
void a2() {
swapcontext(&a_ctx, &b_ctx);
}
void a1() { a2(); }
void b2() {
printf("pausing");
pause(); // interrupt here in the debugger
}
void b1() { b2(); }
int main() {
getcontext(&b_ctx);
b_ctx.uc_stack.ss_sp = b_stack;
b_ctx.uc_stack.ss_size = sizeof(b_stack);
makecontext(&b_ctx, b1, 0);
a1();
}
The set $... command can set registers to their saved values from within GDB at which point bt will find the old stack.
(gdb) bt
#0 0x00007ffff7e8cc23 in __libc_pause () at ../sysdeps/unix/sysv/linux/pause.c:29
#1 0x00005555555551c7 in b2 () at src/so.c:16
#2 0x00005555555551d8 in b1 () at src/so.c:19
#3 0x00007ffff7e13a60 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#4 0x0000000000000000 in ?? ()
(gdb) set $rbp = a_ctx.uc_mcontext.gregs[REG_RBP]
(gdb) set $rip = a_ctx.uc_mcontext.gregs[REG_RIP]
(gdb) set $rsp = a_ctx.uc_mcontext.gregs[REG_RSP]
(gdb) bt
#0 a2 () at src/so.c:10
#1 0x00005555555551a7 in a1 () at src/so.c:12
#2 0x0000555555555234 in main () at src/so.c:26
If you have two threads with two stacks you can query the thread by 'info threads'.
After you know which thread's stack you want to see select it with the 'thread' command. Put the number of the thread after the command.
Then you only need to query the stack by 'bt'