这样做有几种办法。
Test with two instantiations
First, just to make the test a little more interesting by having more
than one instantiation of shared_ptr
, I changed the sample to:
#include <iostream>
#include <memory>
struct Test {
~Test() { std::cout << "in ~Test
"; }
};
struct Test2 {
~Test2() { std::cout << "in ~Test2
"; }
};
int main() {
auto sptr = std::make_shared<Test>();
auto sptr2 = std::make_shared<Test2>();
return 0;
}
然后,我编译并开始调试器使用:
$ clang++ -o prog -g -Wall prog.cc
$ lldb ./prog
1. Use breakpoint set --name
The breakpoint set --name
command sets a breakpoint on all functions
with a given name:
(lldb) breakpoint set --name ~shared_ptr
Breakpoint 1: 2 locations.
(lldb) breakpoint list
Current breakpoints:
1: name = ~shared_ptr , locations = 2
1.1: where = prog`std::shared_ptr<Test2>::~shared_ptr() + 16 at shared_ptr.h:103:11, address = prog[0x0000000000001440], unresolved, hit count = 0
1.2: where = prog`std::shared_ptr<Test>::~shared_ptr() + 16 at shared_ptr.h:103:11, address = prog[0x0000000000001460], unresolved, hit count = 0
It also works with a more complete name, but the __1
stuff should not
be there:
(lldb) br set --name std::__1::shared_ptr<Test>::~shared_ptr
Breakpoint 1: no locations (pending).
WARNING: Unable to resolve breakpoint to any actual locations.
(lldb) br set --name std::shared_ptr<Test>::~shared_ptr
Breakpoint 2: where = prog`std::shared_ptr<Test>::~shared_ptr() + 16 at shared_ptr.h:103:11, address = 0x0000000000001460
注:br
是 bref="https://lldb.llvm.org/use/map.html"的别名(通过 unique prefix 机制)的别名,用于 brebpoint
。
2. Use breakpoint set --method
The breakpoint set --method <name>
command sets a breakpoint on all
methods with the given name:
(lldb) breakpoint set --method ~shared_ptr
Breakpoint 1: 2 locations.
(lldb) breakpoint list
Current breakpoints:
1: name = ~shared_ptr , locations = 2
1.1: where = prog`std::shared_ptr<Test2>::~shared_ptr() + 16 at shared_ptr.h:103:11, address = prog[0x0000000000001440], unresolved, hit count = 0
1.2: where = prog`std::shared_ptr<Test>::~shared_ptr() + 16 at shared_ptr.h:103:11, address = prog[0x0000000000001460], unresolved, hit count = 0
3. Use breakpoint set --func-regex
The breakpoint set --func-regex <regex>
command sets a breakpoint on
all functions whose name matches the regex:
(lldb) breakpoint set --func-regex "^std::shared_ptr<.*>::~shared_ptr()$"
Breakpoint 1: 2 locations.
(lldb) breakpoint list
Current breakpoints:
1: regex = ^std::shared_ptr<.*>::~shared_ptr()$ , locations = 2
1.1: where = prog`std::shared_ptr<Test>::~shared_ptr() + 16 at shared_ptr.h:103:11, address = prog[0x0000000000001460], unresolved, hit count = 0
1.2: where = prog`std::shared_ptr<Test2>::~shared_ptr() + 16 at shared_ptr.h:103:11, address = prog[0x0000000000001440], unresolved, hit count = 0
使用起来比较麻烦,但更精确。
4. Break at the line in the header
With b <file>:<line>
, you can put breakpoints into all instantiations
of a method at that location:
(lldb) b shared_ptr.h:103
warning: (x86_64) /home/scott/wrk/learn/lldb/break-in-shared-ptr-dtor/prog 0x000034a5: DW_AT_specification(0x000000000000088e) has no decl
warning: (x86_64) /home/scott/wrk/learn/lldb/break-in-shared-ptr-dtor/prog 0x000034c6: DW_AT_specification(0x0000000000000110) has no decl
Breakpoint 1: 2 locations.
(lldb) breakpoint list
Current breakpoints:
1: file = shared_ptr.h , line = 103, exact_match = 0, locations = 2
1.1: where = prog`std::shared_ptr<Test2>::~shared_ptr() + 16 at shared_ptr.h:103:11, address = prog[0x0000000000001440], unresolved, hit count = 0
1.2: where = prog`std::shared_ptr<Test>::~shared_ptr() + 16 at shared_ptr.h:103:11, address = prog[0x0000000000001460], unresolved, hit count = 0
This is reasonably easy and precise if you know where the method is
implemented. I don t know why it spews those "has no decl" warnings,
but it s not unusual for LLDB to do that sort of thing.
注: b
和 breakpoint
是不同的命令!
5. Break in a callee
With any of these methods, you can instead put a breakpoint in one of
the destructors defined in your own code:
(lldb) breakpoint set --method ~Test
Breakpoint 1: where = prog`Test::~Test() + 12 at prog.cc:5:25, address = 0x0000000000001e2c
(lldb) run
Process 588466 launched: /home/scott/wrk/learn/lldb/break-in-shared-ptr-dtor/prog (x86_64)
in ~Test2
Process 588466 stopped
* thread #1, name = prog , stop reason = breakpoint 1.1
frame #0: 0x0000555555555e2c prog`Test::~Test(this=0x000055555556cec0) at prog.cc:5:25
2 #include <memory>
3
4 struct Test {
-> 5 ~Test() { std::cout << "in ~Test
"; }
6 };
7
8 struct Test2 {
(lldb) symbol table for <Unknown>.....K [weird msg, I hit Ctrl-C]
error: No auto repeat.
(lldb) bt
* thread #1, name = prog , stop reason = breakpoint 1.1
* frame #0: 0x0000555555555e2c prog`Test::~Test(this=0x000055555556cec0) at prog.cc:5:25
frame #1: 0x0000555555555e19 prog`void __gnu_cxx::new_allocator<Test>::destroy<Test>(this=0x000055555556cec0, __p=0x000055555556cec0) at new_allocator.h:153:10
frame #2: 0x0000555555555dbd prog`void std::allocator_traits<std::allocator<Test>>::destroy<Test>(__a=0x000055555556cec0, __p=0x000055555556cec0) at alloc_traits.h:497:8
frame #3: 0x0000555555555bd6 prog`std::_Sp_counted_ptr_inplace<Test, std::allocator<Test>, (__gnu_cxx::_Lock_policy)2>::_M_dispose(this=0x000055555556ceb0) at shared_ptr_base.h:557:2
frame #4: 0x0000555555555503 prog`std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release(this=0x000055555556ceb0) at shared_ptr_base.h:155:6
frame #5: 0x00005555555554ba prog`std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count(this=0x00007fffffffe4e0) at shared_ptr_base.h:730:11
frame #6: 0x0000555555555579 prog`std::__shared_ptr<Test, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr(this=0x00007fffffffe4d8) at shared_ptr_base.h:1169:31
frame #7: 0x0000555555555465 prog`std::shared_ptr<Test>::~shared_ptr(this=nullptr) at shared_ptr.h:103:11
frame #8: 0x000055555555524f prog`main at prog.cc:16:1
frame #9: 0x00007ffff7a9c0b3 libc.so.6`__libc_start_main + 243
frame #10: 0x000055555555514e prog`_start + 46
Maybe stopping in a callee suffices, or maybe seeing the desired symbol
and its file name in the backtrace helps accomplish the goal.
Documentation link
I got most of this info by reading the
Breakpoint commands
section of the
GDB to LLDB command map, plus
experimentation.