Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Glava14 r.doc
Скачиваний:
2
Добавлен:
01.07.2025
Размер:
548 Кб
Скачать
☆

1 Некоторые вычислительные системы даже вообще не могут работать с адресами, не кратными определенному числу байт.

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

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

Глобальная и локальная память

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

Локальная область памяти — это область памяти, которая выделяется в начале выполнения некоторого фрагмента результирующей программы (блока, функции, процедуры или оператора) и может быть освобождена по завершении выполнения данного фрагмента. Доступ к локальной области памяти всегда запрещен за пределами того фрагмента программы, в котором она выделяется. Это определяется как синтаксическими и семантическими правилами языка, так и кодом результирующей программы. Даже если удастся обойти ограничения, налагаемые входным языком, использование таких областей памяти вне их области видимости приведет к катастрофическим последствиям для результирующей программы.

Распределение памяти на локальные и глобальные области целиком определяется семантикой языка исходной программы. Только зная смысл синтаксических конструкций исходного языка, можно четко сказать, какая из них будет отнесена в глобальную область памяти, а какая — в локальную. Иногда в исходном языке для некоторых конструкций нет четкого разграничения, тогда решение об их отнесении в ту или иную область памяти принимается разработчиками компилятора и может зависеть от используемой версии компилятора. При этом разработчики исходной программы не должны полагаться на тот факт, что один раз принятое решение будет неизменным во всех версиях компилятора.

Рассмотрим для примера фрагмент текста модуля программы на языке Pascal:

Согласно семантике языка Pascal, переменная Globa1_I является глобальной переменной языка и размещается в глобальной области памяти, константа Global_l также является глобальной, но язык не требует, чтобы компилятор обязательно размещал ее в памяти — значение константы может быть непосредственно подставлено в код результирующей программы там, где она используется. Типизированная константа G1obal_2 является глобальной, но в отличие от константы Global_l семантика языка предполагает, что эта константа обязательно будет размещена в памяти, а не в коде программы. Доступность идентификаторов Global_I, Global_2 и Global_l из других модулей зависит от того, где и как они описаны. Например, для компилятора Borland Pascal переменные и константы, описанные в заголовке модулей, доступны из других модулей программы, а переменные и константы, описанные в теле модулей, недоступны, хотя и те и другие являются глобальными.

Параметр Param функции Test, переменная Local_I и константа Local_l являются локальными элементами этой функции. Они не доступны вне пределов данной функции и располагаются в локальной области памяти. Типизированная константа Local_2 представляет собой очень интересный элемент программы. C одной стороны, она не доступна вне пределов функции Test и потому является ее локальным элементом. C другой стороны, как типизированная константа она будет располагаться в глобальной области памяти, хотя ниоткуда извне не может быть доступна (аналогичными конструкциями языка C, например, являются локальные переменные функций, описанные как static).

Семантические особенности языка должны учитывать создатели компилятора, когда разрабатывают модуль распределения памяти. Безусловно, это должен знать и разработчик исходной программы, чтобы не допускать семантических (смысловых) ошибок — этот тип ошибок сложнее всего поддается обнаружению. Так, в приведенном выше примере в качестве результата функции Test может выступать адрес переменной G1obal_I или типизированной константы G1oba1_2. Результатом функции не может быть адрес констант Global_l или Local_l — это запрещено семантикой языка. Гораздо сложнее вопрос с переменной Local_I или параметром функции Param. Будучи элементами локальной области памяти функции Test, они никак не могут выступать в качестве результата функции, потому что он будет использован вне самой функции, когда область ее локальной памяти может уже не существовать. Ho ни синтаксис, ни семантика языка не запрещают использовать адрес этих элементов в качестве результата функции (и далеко не всегда компилятор способен хотя бы обнаружить факт такого использования адреса локальной переменной). Эти особенности языка должен учитывать разработчик программы. A вот адрес типизированной константы Local_2 в принципе может быть результатом функции Test. Ведь хотя она и является локальной константой, но размещается в глобальной области памяти (другое дело, что этим пользоваться не рекомендуется, поскольку нет гарантии, что принцип размещения локальных типизированных констант не изменится с переходом к другой версии компилятора)1.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]