Расположение указателей и глобальных переменных в C

Где указатели и глобальные переменные хранятся в C? Сохраняются ли они в памяти, куче или стеке?

Ответы

Ответ 1

Глобальные переменные могут находиться в нескольких местах, в зависимости от того, как они настроены - например, const globals могут находиться в разделе только для чтения исполняемого файла. "Нормальные" глобалы находятся в разделе "чтение-запись" исполняемого файла. Они вообще не находятся в куче или в стеке. Указатели - это всего лишь тип переменной, поэтому они могут быть там, где вы хотите, чтобы они были (в куче, если вы malloc() их, в стеке, если они являются локальными переменными или в разделе данных, если они глобальны).

Ответ 2

Compile

Когда файл скомпилирован, переменные с "длительностью программы" (статические или глобальные переменные), которые определены в этой "единице компиляции" (в грубых выражениях, "c файл" ) определяют, сколько глобального пространства требуется этой программе, и как он инициализируется.

Ссылка

Когда компоновщик создает ваш исполняемый файл, он объединяет эту информацию и помещает ее в разделы исполняемого файла, используемые для этой цели. Затем компоновщик переходит и меняет все ссылки на эти данные туда, где он будет помещать эти данные в пространство памяти процесса при загрузке программы. Таким образом, указатели на глобальные данные будут похожи на константы в исходном файле; для них не нужно выделять память.

Для нулевых инициализированных или неинициализированных глобальных данных сохраняется только объем пространства, необходимого для таких данных. Для инициализированных данных сохраняются начальные значения.

Загрузить

Когда ваша программа загружена, загрузчик будет заглядывать в файл программы, чтобы указать, сколько нулевых инициализированных данных необходимо, и выделяет достаточно пространства памяти процесса для него и инициализирует все это двоичным нулем. Для инициализированных данных он выделяет память для этого и инициализирует его начальными значениями, сохраненными в exe файле. Он также выделяет области для кучи (используемые malloc()) и стек.

Динамические библиотеки

Если ваш код находится в динамической библиотеке, компоновщик не может знать, где он будет размещать глобальные данные. В этом случае он создает разделы в библиотеке, чтобы указать, где ссылки на глобальные данные, и загрузчик позаботится об изменении ссылок на нужное место при загрузке файла (вот почему вы передаете -fPIC в командной строке gcc для dll). Но так как это делается во время загрузки, к моменту запуска вашей программы размещение данных известно, поэтому загрузчик знает, где эти данные будут указателями на глобальные данные, все равно могут выступать в качестве констант в вашей программе.

Динамическая загрузка

Если вы динамически связываетесь с dll, загрузчик не знает об этом, поэтому вам нужно вызывать функции, которые знают, как загрузить DLL и получить адрес экспортируемых данных и функций.

Ответ 3

Глобальные переменные обычно хранятся в сегменте данных приложения.

Указатели не сохраняются иначе, чем другие переменные (например, если у вас есть локальная переменная типа int*, она будет храниться в стеке, как и любая другая локальная переменная).

Ответ 4

Все распределения, сделанные malloc(), calloc() или realloc(), хранятся в куче, тогда как все локальные переменные хранятся в стеке.

Все глобальные и статические переменные хранятся в сегменте данных, а константы хранятся в сегменте кода.

Ответ 5

Память через malloc() берется из кучи. Это обеспечивает указатель на память.

Подробнее здесь.