堆地址范围内的全局变量的地址 [英] Address of a Global Variable in the Heap Address Range

查看:133
本文介绍了堆地址范围内的全局变量的地址的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I was debugging the MPlayer-1.3.0 source code, and I saw a global variable whose address (returned by GDB or even simple printing) was in the range for the heap allocations, instead of the data section. I checked the heap range using 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

变量定义为int verbose = 0;,位于mp_msg.cline 40处,地址为0x555555b3bbb0,位于[heap]映射中.我什至在它之前和之后检查了一些变量定义:

The variable definition is int verbose = 0;, at line 40 of mp_msg.c and the address is 0x555555b3bbb0, which is in the [heap] mapping. I even checked some variable definitions before and after it:

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;

其中,只有mp_msg_level_all位于数据部分中.感谢您的帮助.

Of these, only mp_msg_level_all is located in the data section. Any help is appreciated.

推荐答案

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

Assuming your question is "why is int verbose = 0; allocated to [heap] memory mapping according to /proc/self/maps ?", the answer is that

  1. 整个[heap]概念确实是久已遗忘的过去的遗物,并且
  2. 传统的[heap].bss之后立即开始,并且它们通常共享相同的映射,因此这里没有 令人惊讶.
  1. the whole [heap] notion is really a relic of the long forgotten past, and
  2. the traditional [heap] starts immediately after the .bss, and they usually share the same mapping, so there is nothing to be surprised about here.

在旧的传统UNIX内存模型中(在线程和mmap成为问题之前),在点1上稍微扩展一点,在堆栈变小的处理器上,内存的上半部分被保留用于内核空间,即堆栈从用户内存的最高端开始,程序.text本身从地址0开始,紧随其后的是.data.bss,然后紧随其后的是堆(brk/sbrk类型).这样可以使堆增长到更高的地址,并为合并的堆+堆提供最大的可用内存.

Expanding on point 1 a bit, in the traditional UNIX memory model of old (before threads and mmap became a thing), on processors where stack grows down, top half of the memory was reserved for the kernel space, stack started at the highest end of user memory, the program .text itself started at address 0, with .data and .bss immediately following, and then heap (the brk / sbrk kind) immediately after. This allowed heap to grow to higher addresses, and gave combined heap+stack the maximum available memory.

在存在线程,共享库和内存映射文件的情况下,该模型根本无法很好地工作,并且已被现代的malloc实现很大程度上废弃,而现代的malloc实现几乎很少打扰到sbrk.取而代之的是,它们只是mmap所需的内存(并且任何此类内存都不会在您在procfs中看到的[heap]中显示).

That model doesn't work well at all in the presence of threads, shared libraries and memory mapped files, and has been largely abandoned by modern malloc implementations, which rarely bother with sbrk at all. Instead they just mmap the memory they need (and any such memory will not show up in [heap] that you see in procfs).

P.S.

  • 将零页面映射到进程空间的想法早已被放弃,因为它只会导致错误.这就是.text在所有现代UNIXen上都从更高地址开始的原因.
  • 给内核提供一半的可用地址空间也是非常浪费的,并且32位Linux开始为内核提供更少的空间.在64位系统上,地址空间不足不再是问题.
  • The idea of mapping zero page into the process space has long been abandoned as it only leads to bugs. This is why .text starts at higher addresses on all modern UNIXen.
  • Giving the kernel half of available address space is also quite wasteful, and 32-bit Linux started to give the kernel much less space. On 64-bit systems running out of address space is no longer an issue.

更新:

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

So you mean that [heap] contains both .bss and part of heap. So, the only way to determine if an address is inside the heap is to trace malloc(),free(),... calls?

我认为我解释得不好.

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

The notion that there is a single region in the process space called "heap" is obsolete. A modern malloc implementation is likely to have multiple thread-specific arenas, obtained from the system via mmap, and a heap-allocated object can be in any one of them.

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

You can't easily say "oh, this address 0x568901234 looks like heap", because it could be anything.

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

What is the standard way to determine the address ranges for virtual memory areas (e.g., .text, heap and .bss) of a process in Linux, if procfs output is obsolete?

在这里,您尝试用有些过时的术语来解释内存布局:在大多数进程中,没有 单个.text.bss,因为每个共享库都具有它自己(除了主要的可执行文件).并且还有许多其他部分(.tls.plt.got等).部分甚至都不是必需完全在运行时– ELF(在运行时)只需要段,而不关心段.

Here again, you are trying to explain memory layout in terms that are somewhat obsolete: there isn't a single .text or .bss in most processes, because each shared library will have its own (in addition to that of the main executable). And there are many additional sections as well (.tls, .plt, .got, etc.) And sections aren't even required at runtime at all -- ELF (at runtime) needs only segments, and doesn't care about sections.

这篇关于堆地址范围内的全局变量的地址的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆