2010-04-15 4 views
3

Где хранятся функции в программе на C++?Назначение функций

Например

int abc() 
{ 
    //where am I stored? 
} 

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

Я смущен. Мой вопрос может показаться смутным для многих из вас, но я не могу помочь.

+1

Что заставляет вас думать, что компилятор фактически хранит все функции в памяти? Все, что вы показали, это то, что в нем хранятся все функции *, которые вы выбрали именно так. –

+0

Чтобы развернуть комментарий Joe, функции могут быть * inlined *, что означает, что функция вызывается вместо того, чтобы вставлять код для вызова этой функции, компилятор вставляет фактический кусок функции. Это означает, что код одной функции может присутствовать несколько раз в течение всей программы. Кроме того, функции, которые никогда не вызываются, могут быть полностью удалены! – AshleysBrain

ответ

9

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

Как только программа начнет работать, распределение памяти для функций не происходит; это делается до запуска программы, загрузчиком программы системы.

Это предполагает «обычную» настольную ОС, поскольку встроенные системы, работающие с кодом из ПЗУ, часто различаются.

+3

Также: он может загружаться динамически виртуальной памятью. – Potatoswatter

2

Местоположение и порядок функций в памяти управляется компоновщиком и может быть отредактирован путем редактирования файла команды компоновщика.

Это важно, особенно во встроенных системах. Например, вы можете указать, какие функции хранятся в быстрой внутренней памяти, а какие - в более медленной внешней памяти. Порядок функций важен для оптимизации кеша и т. Д.

Чтобы узнать, где хранятся каждая функция и (глобальная) переменная, найдите файл * .map, созданный компоновщиком.

0

Для расширения двух других ответов:

На большинстве (не встраиваемый) платформ, когда устройство скомпилированных код и данные хранятся в разделах объектного файла. Компилятор объединяет эти разделы вместе, когда он собирает окончательную программу. В форматах объектов COFF, PE и ELF, например, весь код помещается в раздел .text. Все предварительно инициализированные данные сохраняются в разделе .data или .bss.

Где эти сегменты фактически являются действительно неважны. Когда программа загружена, компоновщик времени выполнения (называемый ld-linux.so на Linux) загрузит всю программу в один или несколько областей памяти, и операционная система будет отображать каждый из разделов в свои сегменты памяти. Это предполагает, что платформа имеет как MMU, так и сегментацию памяти, как на x86. Многие современные операционные системы также рандомизируют местоположения, где эти разделы загружаются для обеспечения безопасности. Поэтому для каждого запуска программы данная функция может не иметь одного и того же адреса.

+0

Сегментированное управление памятью редко используется в наши дни. Даже Windows теперь использует линейную адресацию. Старые программы .COM в DOS полагались на сегменты, но .EXE-программы содержат перемещение информации и, следовательно, не требуют аппаратного обеспечения сегментации. – PauliL

+0

@PauliL: Хотя это правда, концепция все еще существует. Секции программы по-прежнему четко очерчены и могут также существовать на разных страницах, которые используются так же, как и регистры сегментов. – greyfade

0

В некоторых операционных системах функции могут храниться на диске до тех пор, пока они не будут доступны. ОС может зарезервировать область для загрузки этих функций по требованию. Для получения дополнительной информации найдите «Пейджинг операционной системы».

Некоторые компиляторы и компоновщики позволяют программисту определять местоположение функций. Для удобства они определяют сегменты и позволяют размещать сегменты в разных местах.В встроенных системах это позволяет некоторым функциям находиться в ПЗУ, некоторые - в Flash и других в ОЗУ.

В большинстве случаев программам действительно не важно, где находятся функции в памяти. Компилятор генерирует «Независимый код позиции», а операционная система назначает физические адреса при загрузке программы.

+0

Позиция независимого кода и перемещаемого кода - это две разные вещи. Когда загружается перемещаемый код, загрузчик вычисляет абсолютные адреса и обновляет эти адреса в коде. Независимый от положения код не требует перемещения. Адреса являются относительными (например, скачок 215 байт назад от текущего местоположения), поэтому код работает без изменений в любом месте памяти. – PauliL