代码之家  ›  专栏  ›  技术社区  ›  the_endian

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

  •  0
  • the_endian  · 技术社区  · 3 年前

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

    (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
    $10 = 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;
    }
    
    0 回复  |  直到 3 年前
        1
  •  1
  •   jxh    3 年前

    它有效

    这是在linux上测试的。

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

    启动gdb,运行您的流程

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

    此时,当您执行 信息进程映射 ,堆不在表中。

    通过呼叫前进到 malloc

    (gdb) n
    ...
    (gdb) n
    ...
    (gdb) n
    ...
    

    现在,执行时堆位置将可见 信息进程映射

    观察堆的位置

    (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]
    
        2
  •  0
  •   Blindy    3 年前

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