Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Shpory_tyap (1).doc
Скачиваний:
23
Добавлен:
17.04.2019
Размер:
1.05 Mб
Скачать

27. Сборка мусора.

Мусор — такой элемент, который пригоден для повторного использования, но не создается в списке свободного пространства и поэтому недоступен. Мусор может вызвать значительные трудности для систем управления памятью. Если происходит накопление мусора, то доступ­ная память постепенно уменьшается и в результате может случиться, что выполнение про­граммы не сможет продолжаться из-за недостатка свободного пространства. Таким образом, накопление мусора ведет к истощению пригодной для работы памяти.

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

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

Процедура сбора мусора включает 2 стадии:

  1. Маркировка активных элементов (помечаются все элементы кучи, которые активны, т.е. являются частью доступных структур данных). Алгоритм маркировки устанавливает биты сбора мусора всех активных элементов в положение «выключен».

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

Наиболее сложной частью сбора является маркировка. Для процесса маркировки необходимо соблюдение трех условий:

  • любой активный элемент должен быть достижим по цепи указателей, начинающихся вне кучи.

  • должна иметься возможность выявления всех указателей вне кучи, указывающих на элементы внутри нее.

  • для каждого активного элемента должно быть возможно определить все поля внутри него, содержащие указатели на другие элементы кучи.

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

28. Промежуточный код

Промежуточный код можно проектировать.

Например, пром. код получают, просто разбивая сложную структуру некоторых языков на более удобную. Для обращения элементов в качестве пром. кода можно использовать … обобщенный машинный код, который затем транслируется в код реальной машины.

Получение пром. кода возможно до и после распределения памяти. Одним из видов пром. кода являются «4-ки»:

Например, выражение: (-a + b)*(c + d)

Можно представить в виде 4-ки следующим образом:

-a = 1

1+ b = 2

c + d = 3

2*3 = 4

Целые числа соответствуют идентификаторам, присваиваемые компилятором. 4-ки можно считать пром. кодом высокого уровня. Такой код называют 3-х адресным: 2 адреса для операндов (кроме тех случаев, когда имеют место унарные операции) и один для результата. Другой вариант, когда «3-ки» (2-х адресный код) – каждая 3-ка состоит из 2-х адресов – операндов и знаков операции; если сам операнд является 3-кой, то используется ее позиция, что исключает необходимость иметь в каждой 3-ке адрес результата, например:

a + b + c*d

можно представить в виде 4-ок:

a +b = 1

c*d = 2

1 + 2 = 3

И в виде 3-ек:

a +b

c*d

1 + 2

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

Наилучшим решением этой проблемы являются косвенные 3-ки, то есть операнд, ссылающийся на ранее вычисленную 3-ку, должен указать на элемент таблицы, указывающей на 3-ку, а не на саму эту 3-ку.

Как 3-ки так и 4-ки можно применять на выражения и на другие конструкции языков.

Например: а := b

- в виде 4-ки: a := b = 1

- в виде 3-ки: a := b

Аналогично:

if a then b else c fi

Выражение можно считать с тремя операндами, которому требуются 4 адреса как 4-ки и 3 адреса как 3-ки.

В качестве пром. кода может применяться префиксная и постфиксная нотация. В префиксной нотации каждый знак появляется перед своим операндом, а в постфиксной – после. Например: инфиксное выражение a + b в преф-ой нотации имеет вид:

+ a b,

А в постфиксной:

a b +

Инфиксная – обозначение двухместной операции, появляющейся между самими операндами. А с помощью постфиксной и преф-ой нотаций записывают более сложные выражения. Например:

(a + b)*(c + d)

в префиксной форме: * + a b + c d

в постфиксной форме: a b + c d + *

В этих записях скобки («), (») уже не требуются, так как не возникает сомнения относительно того, какие операнды принадлежат к тем или иным знакам операции.

В этих операциях не существует приоритетов знаков операций, хотя при преобразовании инфиксного выражения в префиксные или постфиксные их приоритет нужно указать.

Префиксные и постфиксные выражения можно получить из представления выражения в виде унарного дерева, например:

(a + b) * c + d

Дерево бинарное:

x

/ \

/ \ d

/ \ c

a b

Чтобы получить префиксного выражения дерево обходят сверху в определенном порядке:

Посещение корня, обход левого поддерева сверху, обход правого поддерева сверху, что дает: + * + a b c d

Для получения постфиксного выражения дерево обходят снизу:

Обходят левое поддерево снизу, обходят правое поддерево снизу, посещение корня, в результате получим: a b + c * d +

В качестве терминала промежуточного языка (или объектного) используют команду вида:

Тип-команды, параметры.

Тип команды может быть например, вызовом стандартного вызова операции, тогда параметрами могу быть имя знака операции, адреса операндов и адреса результатов,

Например: STANDOP I I+, A, B, C

I I+ - сложение 2-х целых чисел

A, B, C – служат во время прогона адресами 2-х операндов и результата.

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

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

При получении промежуточного кода для хранения адресов операндов используется стек до тех пор пока не будет напечатан знак операции, т.к. знак операции можно установить во многих языках лишь после того как станут известны операнды. Стек служит также для хранения каждого знака операции на то время, пока не определены два операнда.

Адрес на время прогона обычно соотносится со стеком и каждый такой адрес можно представить тройкой вида:

(тип-адреса, номер блока, смещение)

Тип адреса может быть прямым или косвенным и ссылаться на рабочий стек или стек идентификатора. Он может быть также константой. Номер блока позволяет найти номер уровня блока в таблице блоков. В случае константы номер блока не используется.

Смещение (для адреса стека) показывает смещение значения конкретной рамки стека по отношению к началу стека идентификатора или рабочего стека.

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