Адрес глобальной переменной в диапазоне адресов кучи - PullRequest
0 голосов
/ 06 января 2019

Я отлаживал исходный код 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

Определение переменной - int verbose = 0;, при line 40 из mp_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;

Из них только mp_msg_level_all находится в разделе данных. Любая помощь приветствуется.

Ответы [ 2 ]

0 голосов
/ 07 января 2019

Если ваш вопрос «почему int verbose = 0; выделено для [heap] отображения памяти в соответствии с /proc/self/maps?», Ответ таков:

  1. все [heap] понятие действительно является пережитком давно забытого прошлого, и
  2. традиционный [heap] начинается сразу после .bss, и они обычно разделяют одно и то же отображение, так что ничего здесь не удивит.

Немного расширив точку 1, в традиционной старой модели памяти UNIX (до того как потоки и mmap стали единым целым), на процессорах, где стек уменьшается, верхняя половина памяти была зарезервирована для пространства ядра, стек запущенная в самом верхнем пользовательском запоминающем устройстве, сама программа .text запускалась по адресу 0, сразу после нее следовали .data и .bss, а затем сразу же начиналась куча (тип brk / sbrk). Это позволило куче расти до более высоких адресов, а объединенная куча + стек максимально доступной памяти.

Эта модель не работает вообще при наличии потоков, разделяемых библиотек и файлов отображения памяти, и была в значительной степени заброшена современными malloc реализациями, которые редко вообще беспокоят sbrk. Вместо этого они просто mmap нужной памяти (и любая такая память не будет отображаться в [heap], что вы видите в procfs).

приписка

  • Идея отображения нулевой страницы в пространство процесса давно отброшена, поскольку она приводит только к ошибкам. Вот почему .text начинается с более высоких адресов во всех современных UNIXen.
  • Предоставление ядру половины доступного адресного пространства также довольно расточительно, и 32-битный Linux начал предоставлять ядру намного меньше места. В 64-разрядных системах исчерпание адресного пространства больше не является проблемой.

Обновление:

То есть вы имеете в виду, что [куча] содержит как .bss, так и часть кучи. Таким образом, единственный способ определить, находится ли адрес внутри кучи, состоит в том, чтобы отслеживать вызовы malloc (), free (), ...?

Не думаю, что я объяснил это хорошо.

Понятие о том, что в пространстве процессов есть одна область, называемая "кучей", устарело. Современная реализация malloc, скорее всего, имеет несколько специфичных для потока арен, полученных из системы через mmap, и объект, выделенный в куче, может находиться в любой из них.

Вы не можете легко сказать «о, этот адрес 0x568901234 выглядит как куча», потому что это может быть что угодно.

Каков стандартный способ определения диапазонов адресов для областей виртуальной памяти (например, .text, heap и .bss) процесса в Linux, если вывод procfs устарел?

Здесь снова вы пытаетесь объяснить структуру памяти в терминах, которые несколько устарели: не один .text или .bss в большинстве процессов, потому что каждая общая библиотека будет иметь свою собственный (в дополнение к основному исполняемому файлу). А также есть множество дополнительных секций (.tls, .plt, .got и т. Д.) И секций даже не требуется в время выполнения вообще - ELF (во время выполнения) нуждается только в сегментах и ​​не заботится о разделах.

0 голосов
/ 06 января 2019

mp_msg_level_all находится в разделе данных, потому что оно инициализировано ненулевым значением. Остальные инициализируются в 0 и, как таковые, принадлежат секции bss.

Почему компоновщик решил поместить bss в очевидно диапазон кучи адресов, мы можем только удивляться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...