memory - 检查 pmap 报告的虚拟内存块

标签 memory gdb massif

我发现我的程序存在泄漏。它不会被“valgrind memcheck”捕获(我通过摘要报告确认了这一点,它没有接近我能看到的最高使用率)。使用“valgrind Massif --pages-as-heap”时,我可以得到更接近我的内存使用情况的信息。 但是,它没有报告执行 mmap 并分配大部分内存的部分的完整回溯,而且我也无法检查内存分配,因为我只能在程序被终止后收集 Massif 输出。 我尝试的另一件事是检查占用大量 RSS 空间的内存块。但是我不知道如何查看pmap报告的内存块的内容。将该地址放在 gdb 上并没有帮助。我听说 gdb 使用了一些地址随机化。有人可以帮助我如何获取与 pmap 输出报告的内存位置相对应的符号吗?

最佳答案

putting that addr on gdb dint help.

我不知道“将该地址放在 gdb 上”是什么意思,但正确执行将会有所帮助。

I heard some address randomization is used by gdb.

您听错了:GDB 本身不会进行任何随机化,并且它(默认情况下)禁用操作系统执行的随机化,以便使调试更容易且更具可重复性。

Can some one help me how to get the symbol that corresponds to the memory location reported by pmap output.

您很困惑:根据定义,堆分配的内存没有有任何符号。

好的,让我们通过示例来检查使用 GDB 在 pmap 中可见的内存。让我们首先编译这个程序,它构建一个 100 万长的链表,其中包含一些字符串:

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

typedef struct Node { struct Node *next; char payload[64]; } Node;

int main()
{
  int j;   
  Node *head = NULL;

  for (j = 0; j < 1000000; j++) {
    Node *n = malloc(sizeof(*n));
    n->next = head;
    sprintf(n->payload, "string %d", j);
    head = n;
  }
  return 0;
}

gcc -Wall -g -std=c99 t.c && gdb -q ./a.out

(gdb) b 17
Breakpoint 1 at 0x4005e3: file t.c, line 17.
(gdb) r
Starting program: /tmp/a.out

Breakpoint 1, main () at t.c:17
17    return 0;

现在我们可以使用 pmap 检查程序:

(gdb) info prog
    Using the running image of child process 23785.
Program stopped at 0x4005e3.
It stopped at breakpoint 1.
Type "info stack" or "info registers" for more information.
(gdb) shell pmap 23785
23785:   /tmp/a.out
0000000000400000      4K r-x-- a.out
0000000000600000      4K r---- a.out
0000000000601000      4K rw--- a.out
0000000000602000  78144K rw---   [ anon ]
00007ffff7a11000   1784K r-x-- libc-2.19.so
00007ffff7bcf000   2048K ----- libc-2.19.so
00007ffff7dcf000     16K r---- libc-2.19.so
00007ffff7dd3000      8K rw--- libc-2.19.so
00007ffff7dd5000     20K rw---   [ anon ]
00007ffff7dda000    140K r-x-- ld-2.19.so
00007ffff7fd1000     12K rw---   [ anon ]
00007ffff7ff6000      8K rw---   [ anon ]
00007ffff7ff8000      8K r----   [ anon ]
00007ffff7ffa000      8K r-x--   [ anon ]
00007ffff7ffc000      4K r---- ld-2.19.so
00007ffff7ffd000      4K rw--- ld-2.19.so
00007ffff7ffe000      4K rw---   [ anon ]
00007ffffffde000    132K rw---   [ stack ]
ffffffffff600000      4K r-x--   [ anon ]
 total            82356K

很明显,从 0x602000 开始的 78MiB 的 anon 空间一定是我们大部分数据所在的位置。 (您还可以通过单步执行循环几次来验证这一点。)

我们如何查看这些数据?就像这样:

(gdb) x/30gx 0x602000
0x602000:   0x0000000000000000  0x0000000000000051
0x602010:   0x0000000000000000  0x3020676e69727473
0x602020:   0x0000000000000000  0x0000000000000000
0x602030:   0x0000000000000000  0x0000000000000000
0x602040:   0x0000000000000000  0x0000000000000000
0x602050:   0x0000000000000000  0x0000000000000051
0x602060:   0x0000000000602010  0x3120676e69727473
0x602070:   0x0000000000000000  0x0000000000000000
0x602080:   0x0000000000000000  0x0000000000000000
0x602090:   0x0000000000000000  0x0000000000000000
0x6020a0:   0x0000000000000000  0x0000000000000051
0x6020b0:   0x0000000000602060  0x3220676e69727473
0x6020c0:   0x0000000000000000  0x0000000000000000
0x6020d0:   0x0000000000000000  0x0000000000000000
0x6020e0:   0x0000000000000000  0x0000000000000000

您立即可以注意到在 0x6020180x6020680x6020b8 处有 ASCII 字符串。

您可以像这样检查这些字符串:

(gdb) x/s 0x602018
0x602018:   "string 0"
(gdb) x/s 0x602068
0x602068:   "string 1"
(gdb) x/s 0x6020b8
0x6020b8:   "string 2"

您还可以注意到,在 0x602060 处有一个指向 0x602010 的指针,在 0x6020b0 处有一个指向 0x602060 的指针.

这让您猜测 0x602060 处有一个节点,0x6020b0 处有另一个节点。你可以证实这个猜测:

(gdb) p *(Node*)0x602060
$1 = {next = 0x602010, payload = "string 1", '\000' <repeats 55 times>}
(gdb) p *(Node*)0x6020b0
$2 = {next = 0x602060, payload = "string 2", '\000' <repeats 55 times>}

这就是它的全部

关于memory - 检查 pmap 报告的虚拟内存块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46851675/

相关文章:

ruby-on-rails - 有没有更有效的方法来存储商店的营业时间?

memory - 在没有 avr-libc 的情况下将数据存储在 RAM 中。如何使用自定义链接器脚本和初始化代码配置正确的内存部分?

gdb - 如何阻止 gdb 单步执行 Fortran 代码中的内部函数?

c++ - 在 gdb 中找不到 GLIBCXX

memory - 在 "killed 9"进程上使用 massif

c++ - Valgrind 的地 block 工具不会分析我的应用程序

android - 如何获取我的 android 设备的内存使用情况

c - 为什么结构体的内存副本没有按预期将字节复制到字节流?

assembly - 使用 gdb 实时编辑代码