Память для типов данных (RTTI-информация)

 

Современные компиляторы с объектно-ориентированных языков программиро­вания предусматривают, что результирующая программа может обрабатывать не только переменные, константы и другие структуры данных, но и информацию о типах данных, описанных в исходной программе. Эта информация получила на­звание RTTI – Run Time Type Information – “информация о типах во время вы­полнения”.

Состав RTTI-информации определяется семантикой входного языка и реализа­цией компилятора. Как правило, для каждого типа данных в объектно-ориенти­рованном языке программирования создается уникальный идентификатор типа данных, который используется для сопоставления типов. Для него может хра­ниться наименование типа, а также другая служебная информация, которая ис­пользуется компилятором в коде результирующей программы. Вся эта инфор­мация может быть в той или иной мере доступна пользователю. Еще одна цель хранения RTTI-информации – обеспечить корректный механизм вызова вирту­альных процедур и функций (так называемое “позднее связывание”), предусмот­ренный во всех объектно-ориентированных языках программирования.

RTTI-информация хранится в результирующей программе в виде RTTI-таблицы. RTTI-таблица представляет собой глобальную статическую структуру дан­ных, которая создается и заполняется в момент начала выполнения результи­рующей программы. Компилятор с объектно-ориентированного входного языка отвечает за порождение в результирующей программе кода, ответственного за заполнение RTTI-таблицы.

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

В принципе, всю эту информацию можно было бы разместить непосредственно в памяти, статически или динамически отводимой для каждого экземпляра объ­екта (класса) того или иного типа. Но поскольку данная информация для всех объектов одного и того же типа совпадает, то это привело бы к нерациональному использованию оперативной памяти. Поэтому компилятор размещает всю инфор­мацию по типу данных в одном месте, а каждому экземпляру объекта (класса) при выделении памяти для него добавляет только небольшой объем служебной информации, связывающей этот объект с соответствующим ему типом данных (как правило, эта служебная информация является указателем на нужную область данных в RTTI-таблице). При статическом распределении памяти под экземпля­ры объектов (классов) компилятор сам помещает в нее необходимую служебную информацию, при динамическом распределении – порождает код, который за­полнит эту информацию во время выполнения программы (поскольку RTTI-таблица является статической областью данных, адрес ее известен и фиксиро­ван).

На рис. 12 приведена схема, иллюстрирующая построение RTTI-таблицы и ее связь с экземплярами объектов в результирующей программе.

 

 

Рис. 12. Взаимосвязь RTTI-таблицы с экземплярами объектов

в результирующей программе

 

Компилятор всегда сам автоматически строит код, ответственный в результи­рующей программе за создание и заполнение RTTI-таблицы и за ее взаимосвязь с экземплярами объектов (классов) различных типов. Разработчику не надо заботиться об этом, тем более что он, как правило, не может воздействовать на слу­жебную информацию, помещаемую компилятором в RTTI-таблицу.

Проблемы могут появиться в том случае, когда некоторая программа взаимодей­ствует с динамически загружаемой библиотекой. При этом могут возникнуть ситуации, вызванные несоответствием типов данных в программе и библиотеке, хотя и та и другая могут быть построены на одном и том же входном языке с по­мощью одного и того же компилятора. Дело в том, что код инициализации про­граммы, порождаемый компилятором, ответственен за создание и заполнение своей RTTI-таблицы, а код инициализации библиотеки, порождаемый тем же компилятором, – своей RTTI-таблицы. Если программа и динамически загру­жаемая библиотека работают с одними и теми же типами данных, то эти RTTI-таблицы будут полностью совпадать, но при этом они не будут одной и той же таблицей. Это уже должен учитывать разработчик программы при проверке со­ответствия типов данных.

Еще большие сложности могут возникнуть, если программа, построенная на ос­нове входного объектно-ориентированного языка программирования, будет взаи­модействовать с библиотекой или программой, построенной на основе другого объектно-ориентированного языка (или даже построенной на том же языке, но с помощью другого компилятора). Поскольку формат RTTI-таблиц и состав хра­нимой в них служебной информации не специфицированы для всех языков про­граммирования, то они полностью зависят от используемой версии компилято­ра. Соответствующим образом различается и порождаемый компилятором код результирующей программы. В общем случае организовать такого рода взаимо­действие между двумя фрагментами кода, порожденного двумя различными ком­пиляторами, напрямую практически невозможно.

 

Генерация кода