LLDB:在 std::shared_ptr<T> 析构函数上设置断点

问题描述 投票:0回答:1

如何在析构函数

lldb
~shared_ptr
中设置符号断点?


上下文:我们想在演示程序中检查一个简单实现的前向链表的堆栈溢出,其中丢弃包含 100,000 个元素的列表会溢出,因为每个节点的析构函数都会触发它的

->next
析构函数。

样本文件

#include <memory>

class Test {
public:
    Test() : a(1) { }
    
    int a;
};

int main() {
    auto sptr = std::make_shared<Test>();
    return 0;
}

尝试断点(最后一个是自动完成建议的):

(lldb) br set --name std::__1::shared_ptr<Test>::~shared_ptr
WARNING:  Unable to resolve breakpoint to any actual locations.
(lldb) br set --name std::__1::shared_ptr<Test>::~shared_ptr[abi:v160006]()
WARNING:  Unable to resolve breakpoint to any actual locations.
c++ std shared-ptr smart-pointers lldb
1个回答
0
投票

有多种方法可以做到这一点。

使用两个实例进行测试

首先,只是为了让测试变得更有趣一点 比

shared_ptr
的一个实例,我将示例更改为:

#include <iostream>
#include <memory>

struct Test {
    ~Test() { std::cout << "in ~Test\n"; }
};

struct Test2 {
    ~Test2() { std::cout << "in ~Test2\n"; }
};

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.使用
breakpoint set --name

breakpoint set --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 

它也可以使用更完整的名称,但是

__1
的东西不应该 在那里:

(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
breakpoint
的别名。

2.使用
breakpoint set --method

breakpoint set --method <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.使用
breakpoint set --func-regex

breakpoint set --func-regex <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.在标题行处断开

使用

b <file>:<line>
,您可以将断点放入所有实例化中 该位置的方法:

(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 

如果您知道该方法在哪里,那么这是相当简单和精确的 实施的。我不知道为什么它会发出那些“没有 decl”警告, 但 LLDB 做这类事情并不罕见。

注意:

b
breakpoint
是不同的命令!

5.闯入被叫者

使用这些方法中的任何一种,您都可以在其中一个中放置一个断点 您自己的代码中定义的析构函数:

(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\n"; }
   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

也许停在被调用者就足够了,或者也许看到所需的符号 其在回溯中的文件名有助于实现目标。

文档链接

我通过阅读以下内容获得了大部分信息 断点命令 的部分 GDB 到 LLDB 命令映射,加上 实验。

© www.soinside.com 2019 - 2024. All rights reserved.