为什么 GDB 不在任何地方显示这个堆地址?

Why is GDB not displaying this heap address anywhere?

我正在调试一个程序并且有以下内容:

(gdb) info proc map
Mapped address spaces:

          Start Addr           End Addr       Size     Offset objfile
            0x400000           0x401000     0x1000        0x0 /home/user/code/c/overread
            0x401000           0x402000     0x1000     0x1000 /home/user/code/c/overread
            0x402000           0x403000     0x1000     0x2000 /home/user/code/c/overread
            0x403000           0x404000     0x1000     0x2000 /home/user/code/c/overread
            0x404000           0x405000     0x1000     0x3000 /home/user/code/c/overread
      0x7f398ba54000     0x7f398ba7a000    0x26000        0x0 /usr/lib64/libc-2.32.so
      0x7f398ba7a000     0x7f398bbc9000   0x14f000    0x26000 /usr/lib64/libc-2.32.so
      0x7f398bbc9000     0x7f398bc14000    0x4b000   0x175000 /usr/lib64/libc-2.32.so
      0x7f398bc14000     0x7f398bc15000     0x1000   0x1c0000 /usr/lib64/libc-2.32.so
      0x7f398bc15000     0x7f398bc18000     0x3000   0x1c0000 /usr/lib64/libc-2.32.so
      0x7f398bc18000     0x7f398bc1b000     0x3000   0x1c3000 /usr/lib64/libc-2.32.so
      0x7f398bc41000     0x7f398bc42000     0x1000        0x0 /usr/lib64/ld-2.32.so
      0x7f398bc42000     0x7f398bc63000    0x21000     0x1000 /usr/lib64/ld-2.32.so
      0x7f398bc63000     0x7f398bc6c000     0x9000    0x22000 /usr/lib64/ld-2.32.so
      0x7f398bc6c000     0x7f398bc6d000     0x1000    0x2a000 /usr/lib64/ld-2.32.so
      0x7f398bc6d000     0x7f398bc6f000     0x2000    0x2b000 /usr/lib64/ld-2.32.so
(gdb) p heap_buffer
 = 0x12942a0 "BBBBB"

我不知道为什么地址 0x12942a0 没有出现在流程图范围内的任何地方,但我可以取消引用它。为什么会这样?

参考程序(显然是一个学习重读的实验程序):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int agrc, char **argv)
{
    int parsed_argv = atoi(argv[1]);
    char stack_buffer[5] = "AAAAA";
    char *heap_buffer = malloc(6);
    // No NULL check, hehe
    strcpy(heap_buffer, "BBBBB");
    int i;
    for(i = 0; i < parsed_argv; ++i)
    {
        //putchar(stack_buffer[i]);
        putchar(heap_buffer[i]);
    }
    putchar('\n');
    free(heap_buffer);
    return EXIT_SUCCESS;
}

它不是二进制文件的内存映射视图 (.so),它是指向您的 OS 提供给您使用的虚拟内存的指针(通过 malloc)。

有效

这是在 linux.

上测试的

info proc mappings确实可以揭示堆的位置。但是,您需要先在一些动态分配后提前执行代码,否则堆区域不会分配给您的进程。

启动 gdb,运行 你的进程

$ gdb ./a.out
...
(gdb) break main
...
(gdb) run blahblah
...

此时,当您执行info proc mappings时,table中不存在堆。

提前通过对 malloc

的调用
(gdb) n
...
(gdb) n
...
(gdb) n
...

现在,当您执行 info proc mappings

时,堆位置将可见

观察堆位置

(gdb) info proc mappings
...
            0x601000           0x622000    0x21000          0                                   [heap]
...

当然,您 gdb 为您的过程打印的位置可能与我显示的不同。

此信息位于 /proc

如果您知道进程的进程 ID,可以在 /proc/<pid>/maps 中查找相同的信息。

$ ps
  PID TTY          TIME CMD
21015 pts/62   00:00:00 bash
21629 pts/62   00:00:00 gdb
21631 pts/62   00:00:00 a.out
32825 pts/62   00:00:00 ps
$ cat /proc/21631/maps | grep heap
00601000-00622000 rw-p 00000000 00:00 0                                  [heap]