Где указатели и глобальные переменные хранятся в C? Они сохраняются в памяти, "куче" или стеке?
Глобальные переменные могут находиться в нескольких местах, в зависимости от того, как они настроены - например, глобальные переменные const
могут находиться в разделе исполняемого файла, доступном только для чтения. . «Обычные» глобальные объекты находятся в секции чтения-записи исполняемого файла. Их вообще нет в куче или стеке. Указатели - это просто тип переменных, поэтому они могут быть там, где вы хотите, чтобы они были (в куче, если вы malloc ()
их, в стеке, если они локальные переменные, или в разделе данных если они глобальные).
Память через malloc ()
берется из кучи. Это дает указатель на память.
Подробнее здесь .
Глобальные переменные обычно хранятся в сегменте данных приложения.
Указатели не хранятся иначе, чем другие переменные (например, если у вас есть локальная переменная типа int *
, она будет храниться в стеке, как и любая другая локальная переменная).
Когда файл компилируется, переменные с "длительностью программы" (статические или глобальные переменные), которые определены внутри этой "единицы компиляции" (грубо говоря, "c-файла"), определяют, сколько глобального пространства нужно этой программе, и как она инициализируется.
Когда компоновщик создает ваш исполняемый файл, он объединяет эту информацию и помещает ее в секции исполняемого файла, используемые для этой цели. Затем компоновщик перебирает и изменяет все ссылки на эти данные, чтобы поместить их в пространство памяти процесса при загрузке программы. Таким образом, указатели на глобальные данные будут подобны константам в вашем исходном файле; для них не нужно выделять память.
Для нуль-инициализированных или неинициализированных глобальных данных хранится только тот объем памяти, который необходим для этих данных. Для инициализированных данных сохраняются начальные значения.
Когда ваша программа загружается, загрузчик заглядывает в файл программы, чтобы определить, сколько нужно нулевых инициализированных данных, выделяет для них достаточное количество места в памяти процесса и инициализирует их двоичным нулем. Для инициализированных данных выделяется память, и они инициализируются начальными значениями, сохраненными в exe-файле. Он также выделяет области для кучи (используемой malloc()) и стека.
Если ваш код находится в динамической библиотеке, компоновщик не может знать, куда он поместит глобальные данные. В этом случае он создает секции в библиотеке, чтобы указать ей, где находятся ссылки на глобальные данные, а загрузчик заботится об изменении ссылок, чтобы они указывали на нужное место, когда он загружает файл (вот почему вы передаете -fPIC в командной строке gcc для dll). Но поскольку это делается во время загрузки, к моменту выполнения вашей программы расположение данных уже известно, поэтому загрузчик знает, где эти данные будут находиться Указатели на глобальные данные все еще могут действовать как константы в вашей программе.
Если вы динамически связываетесь с dll, загрузчик не знает об этом, поэтому вам приходится вызывать функции, которые знают, как загрузить dll и получить адрес ее экспортируемых данных и функций.