堆地址范围中的全局变量的地址

The*_*mad 2 c heap-memory memory-layout mplayer

我正在调试MPlayer-1.3.0源代码,我看到一个全局变量,其地址(由GDB简单打印返回或甚至简单打印)都在堆分配的范围内,而不是数据部分.我使用了检查堆范围procfs.

555555554000-555555834000 r-xp 00000000 08:12 798876  /usr/bin/mplayer
555555a33000-555555b25000 r--p 002df000 08:12 798876  /usr/bin/mplayer
555555b25000-555555b2b000 rw-p 003d1000 08:12 798876  /usr/bin/mplayer
555555b2b000-555556479000 rw-p 00000000 00:00 0       [heap]
7fffc3fff000-7fffc8000000 rw-s 00000000 00:16 1932    /dev/shm/pulse-shm-3887887751
Run Code Online (Sandbox Code Playgroud)

变量的定义是int verbose = 0;,在line 40mp_msg.c和地址是0x555555b3bbb0,这是在[heap]映射.我甚至在它之前和之后检查了一些变量定义:

int mp_msg_levels[MSGT_MAX]; // verbose level of this module. initialized to -2
int mp_msg_level_all = MSGL_STATUS;
int verbose = 0;
int mp_msg_color = 0;
int mp_msg_module = 0;
Run Code Online (Sandbox Code Playgroud)

其中,仅mp_msg_level_all位于数据部分.任何帮助表示赞赏.

Emp*_*ian 5

假设你的问题是"为什么按照?int verbose = 0;分配给[heap]内存映射/proc/self/maps",答案是这样的

  1. 整个[heap]概念实际上是长期被遗忘的过去的遗物,而且
  2. 传统[heap]之后立即开始.bss,并且它们通常共享相同的映射,因此这里没有什么可惊讶的.

在旧的传统UNIX内存模型(在线程之前mmap成为一个东西)上扩展第1点,在堆栈增长的处理器上,内存的上半部分保留用于内核空间,堆栈在最高端开始用户存储器,该程序.text本身开始于地址0℃,用.data.bss立即以下,然后堆(该brk/ sbrk种类)之后.这允许堆增长到更高的地址,并为组合堆+堆栈提供最大可用内存.

在线程,共享库和内存映射文件的存在下,该模型根本不能很好地工作,并且现在malloc很少被现代实现所抛弃,而这些实现很少受到打扰sbrk.相反,他们只mmap需要他们需要的记忆(任何这样的记忆都不会出现在[heap]你看到的内容中procfs).

PS

  • 将零页面映射到流程空间的想法早已被放弃,因为它只会导致错误.这就是为什么.text从所有现代UNIXen上的更高地址开始.
  • 为内核提供一半的可用地址空间也非常浪费,而32位Linux开始为内核提供更少的空间.在64位系统上,用完地址空间不再是问题.

更新:

所以你的意思是[heap]包含.bss和堆的一部分.因此,确定地址是否在堆内的唯一方法是跟踪malloc(),free(),...调用?

我不认为我解释得这么好.

过程空间中有一个称为"堆"的区域的概念已经过时.现代malloc实现可能具有多个特定于线程的竞技场,从系统通过获得mmap,并且堆分配的对象可以在其中任何一个中.

你不能轻易说"哦,这个地址0x568901234看起来像堆",因为它可能是任何东西.

如果procfs输出已过时,那么确定Linux中进程的虚拟内存区域(例如.text,heap和.bss)的地址范围的标准方法是什么?

在这里,您试图用有些过时的术语来解释内存布局:没有单个.text.bss大多数进程,因为每个共享库都有自己的(除了主可执行文件之外).还有许多额外的部分,以及(.tls,.plt,.got等)部分甚至没有需要在运行时在所有- ELF(在运行时)只需要细分,并且不关心的部分.