Адрес глобальной переменной в диапазоне адресов кучи

Я отлаживал 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 ответа

Решение

Предполагая, что ваш вопрос "почему 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).

PS

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

Обновить:

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

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

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

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

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

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

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

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

Другие вопросы по тегам