【问题标题】:Break on variable being freed中断被释放的变量
【发布时间】:2016-01-09 02:11:00
【问题描述】:

有一种方法可以打破被释放的变量/内存地址吗?一个简单的观察点是否适用于这种情况?

场景,当程序释放变量时我得到一个段错误,显然有问题的变量被释放了两次,我需要知道它第一次被释放的位置。

PS:lldb 和 gdb,如果可能的话,对于两个相应的命令。

【问题讨论】:

  • 不是您问题的答案,但如果您使用的是 Linux 之类的环境,其中 valgrind 可用,valgrind 对跟踪此类错误非常有用。
  • 使用valgrind 或诸如 Electric Fence 之类的 malloc 调试器可能更容易。
  • 嗯,linux环境,我去看看。
  • 如果您使用 clang 作为编译器,您也可以将 ASAN 用于相同目的(即clang.llvm.org/docs/AddressSanitizer.html
  • @JimIngham,好点,我会看看,看起来很不错!谢谢:)

标签: c debugging gdb lldb


【解决方案1】:

如何在gdb

gdb 中,您可以通过编写break <em>location</em> if <em>condition</em> 来设置条件断点

这意味着为了打破free函数被调用的指针指向一些动态分配的数据,我们首先必须获得动态分配的数据的地址,然后设置一个断点具有合适的条件。

进一步阅读



设置实验

/tmp% cat > foo.c <<EOF
> #include <stdlib.h>
> 
> void some_function (int * p) {
>   free (p);
> }
> 
> int main () {
>   int * p = malloc (sizeof (int));
> 
>   some_function (p);
> 
>   free (p);
> 
>   return 0;
> }
> EOF
/tmp% gcc -g foo.c -o a.out

冒险

/tmp% <b>gdb ./a.out</b>

我们需要做的第一件事是找到一个合适的断点,这样我们就可以期待我们想要观察的变量的内容,更具体地说是动态分配内存的地址。


(gdb) list main
2   
3   void some_function (int * p) {
4     free (p);
5   }
6   
7   int main () {
8     int * p = malloc (sizeof (int));
9   
10    some_function (p);
11

然后我们将在一个合适的地方设置一个断点,在本例中是9行——然后我们运行应用程序来查看存储在p中的值是什么。


(gdb) break 9
Breakpoint 1 at 0x400577: file foo.c, line 9.
(gdb) run
Starting program: /tmp/a.out 

Breakpoint 1, main () at foo.c:10
(gdb) print p
$1 = (int *) 0x601010

当我们以free 的形式知道要监控的地址时,我们可以轻松地在所需位置设置条件断点。首先,我们需要确保 free 的名称实际上与我们的想法相同。

(gdb) disas main
Dump of assembler code for function main:
   0x0000000000400561 : push   %rbp
   0x0000000000400562 : mov    %rsp,%rbp
   0x0000000000400565 : sub    $0x10,%rsp
   0x0000000000400569 : mov    $0x4,%edi
   0x000000000040056e :    callq  0x400440 <malloc@plt>
   0x0000000000400573 :    mov    %rax,-0x8(%rbp)
=> 0x0000000000400577 :    mov    -0x8(%rbp),%rax
   0x000000000040057b :    mov    %rax,%rdi
   0x000000000040057e :    callq  0x400546 <some_function>
   0x0000000000400583 :    mov    -0x8(%rbp),%rax
   0x0000000000400587 :    mov    %rax,%rdi
   0x000000000040058a :    callq  0x400410 <free@plt>
   0x000000000040058f :    mov    $0x0,%eax
   0x0000000000400594 :    leaveq 
   0x0000000000400595 :    retq

我们现在可以创建断点,并继续执行以查看我们的数据在哪里被释放:

(gdb) break free@plt if $rdi == 0x601010
Breakpoint 2 at 0x400410 (3 locations)
(gdb) cont
Continuing.

Breakpoint 2, 0x0000000000400410 in free@plt ()
(gdb) backtrace
#0  0x0000000000400410 in free@plt ()
#1  0x000000000040055e in some_function (p=0x601010) at foo.c:4
#2  0x0000000000400583 in main () at foo.c:10
(gdb) cont
Continuing.

Breakpoint 2, 0x0000000000400410 in free@plt ()
(gdb) backtrace
#0  0x0000000000400410 in free@plt ()
#1  0x000000000040058f in main () at foo.c:12
(gdb) cont
Continuing.
*** Error in `/tmp/a.out': double free or corruption (fasttop): 0x0000000000601010 ***
...

【讨论】:

    猜你喜欢
    • 2013-02-09
    • 2011-05-26
    • 1970-01-01
    • 1970-01-01
    • 2011-09-22
    • 2018-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多