Вот часто слышно: переменные/данные располагаются в стеке, переменные/данные располагаются в куче, память выделяется там и там...
Со стеком я более или менее разобрался, а вот что такое эта "куча", для чего она служит и, самое главное, ГДЕ она располагается в адресном пространстве процесса, относительно того же стека или секции кода, а также секции данных (как последняя с ним связана и какие именно данные лежат в Ней?)?
И такой вопрос: куда попадают локальные переменные в программе (в стек, правильно?), а вот куда Глобальные, в какую из вышеперечисленных сущностей?
Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице. Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.
14-01-2007 00:04 | Комментарий к предыдущим ответам
Хорошо бы эту микролекцию в Лицей поместить.
Уже без меня поместили :) Только не в Лицей, а в список offtopic-вопросов. А для Лицея это никак не подходит - в Лицее публикуются ЦИКЛЫ статей.
Спасибо, Антон! Теперь всё становится на свои места.
Некоторые дополнения: строковые константы зашиваются компилятором куда-то после кода функции (каждой, видимо).
А адрес глобальных переменных, я выяснил, указывает в то место, где располагается загадочная секция под названием BSS.
А вот за что отвечает секция DATA? Какие данные лежат Там?
Да, а сегмент данных на какую секцию указывает в дельфийских программах? Как с ним связан регистр CS, как он используется машиной?
И ещё остался вопрос: где располагается эта куча - динамическая память? Какой у неё обычно диапазон адресов, где её вообще искать?
И на самом деле есть ещё одна область памяти, где могут размещаться переменные. Это TLS - thread local storage. С каждой нитью связывается такой блок памяти. Чтобы переменная попала туда, надо объявить её как глобальную, но со словом threadvar вместо var. Тогда для каждой нити будет создаваться независимая копия этой переменной.
Локальные переменные попадают в стек. В прологе функции (т.е. в коде, с которого она начинается) в стеке резервируется место для них, в эпилоге - освобождается. Параметры функций тоже располагаются в стеке. Перед вызовом функции они помещаются в стек, затем в эпилоге функции (для моделей вызова register, stdcall, pascal) или в коде, следующем сразу за вызовом функции (для модели вызова cdecl) эта память возвращается стеку. При этом ещё один нюанс - при модели вызова register, которая принята по умолчанию, часть параметров может передаваться через регистры, а не через стек, если компилятор решит, что это будет оптимальнее. А вещественные параметры могут также передаваться через стек FPU.
Сегмент данных - это область памяти, используемая для хранения глобальных переменных и типизированных констант (потому что типизированные константы по своей внутренней сути те же глобальные переменные, только компилятор искусственно ограничивает возможности их изменения). Размер сегмента данных определяется на этапе компиляции и не меняется в процессе работыпрограммы.
Ещё остаётся так называемая динамическая память - память, которую программа может выделять и освобождать по мере необходимости. Понятно, что при этом надо как-то вести учёт занятых и свободных участков памяти, уметь находить свободные участки и т.п. - одним словом, как-то управлять этой памятью. Существует несколько способов управления, но в Windows используется практически только один из них - "куча", поэтому слова "куча" и "динамическая память" обычно используются как синонимы.
В Delphi есть специальный блок, называемый менеджер памяти - он отвечает за выделение и освобождение динамической памяти. Работает он так: запрашивает у системы большие блоки памяти с помощью VirtualAlloc, а потом по мере необходимости выделяет в них более мелкие куски и возвращает указатели на них.
Если быть точным, переменные не могут размещаться в куче. Переменные всегда размещаются либо в стеке, либо в сегменте данных. Но переменная может быть указателем, а этот указатель будет указывать на какую-то область памяти, выделенную в куче. Например, так работают все переменные типа string - они являются указателями, а сама строка и некоторая дополнительная информация о ней находится в динамической памяти, и при операциях со строками при необходимости выполняется перераспределение этой памяти.
Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Функция может не работать в некоторых версиях броузеров.