В таблице символов для кода С++ содержатся имена функций вместе с именами классов?

Я просматриваю различные сообщения о том, содержит ли таблица символов для кода на С++ имя функции вместе с именем класса. Что-то, что я мог найти в сообщении, это то, что он зависит от типа компилятора,

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

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

Я не мог понять, зависит ли это от компилятора или нет? Я предполагал, что компилятор (для кода на С++) будет помещать имена функций с именами классов в таблицу, будь то одиночный или многопроходный компилятор. Как это зависит от проходов? У меня нет такого большого знания. Более того, может ли кто-нибудь показать образец таблицы символов для простого класса С++, как бы он выглядел (имена функций с именем класса)?

Ответы

Ответ 1

Большинство учебников по компиляторам расскажут вам о таблицах символов и часто расскажут вам о скромной сложности langauge, такой как Pascal. Вы не найдете информацию о таблицах символов С++ в учебнике; это слишком загадочно.

Мы предлагаем полный интерфейс С++ 14 для нашего инструментария DMS Software Reengineering Toolkit. Он анализирует С++, строит подробные AST и выполняет разрешение имен и типов, которое включает в себя создание точной таблицы символов.

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

OP специально спросила, что происходит с классами. Следующая диаграмма показывает это для крошечной программы на С++ в верхнем левом углу. В остальной части диаграммы показаны поля, которые представляют собой то, что мы называем "пространствами символов" (или "областями" ), которые являются, по существу, хэш-таблицами, отображающими имена символов (каждый ящик содержит список символов, которыми он владеет) к информации, которую DMS знает об этом символе (расположение исходного файла определения, список узлов AST, которые ссылаются на определение, и сложный союз, который представляет тип, и который, в свою очередь, может указывать на другие типы). Стрелки показывают, как связаны пространства символов; стрелка из пространства A в пространство B означает, что "область A содержится в пределах области B". Обычно процесс поиска пространства символов, поиск области A для символа x, продолжит поиск в области B, если x не найден в A. Вы заметите, что стрелки нумеруются с целым числом; это говорит поисковой машине сначала взглянуть в область с наименьшим номером родителя, прежде чем пытаться искать области с помощью стрелок с большими числами. Так упорядочиваются области (обратите внимание, что класс C наследует от A и B; любой поиск поля в классе C, такой как "b", будет вынужден сначала просмотреть область действия A, а затем в области для B. В таким образом, выполняются правила поиска С++.

Обратите внимание, что имена классов записываются в (уникальное) глобальное пространство имен, потому что они объявлены на верхнем уровне. Если бы они были определены в некотором явном пространстве имен, тогда пространство имён имело бы собственное пространство символов, которое записало объявленные классы, а само пространство имен было бы записано в глобальном пространстве символов.

С++ Symbol Table: Class Perspective

OP не спрашивал, как выглядит таблица символов для тел функций, но у меня просто есть иллюстративный слайд для этого, тоже ниже. Символьные пространства работают одинаково. То, что показано на этом слайде, - это связь между пространством символов и областью области, которую он представляет. Эта привязка фактически реализуется указателем, связанным с пространством символов, с соответствующим AST (s, определения пространства имен могут быть разбросаны по множеству мест).

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

С++ Symbol Table: Function Perspective

Как правило, детали того, как организована таблица символов, полностью зависит от компилятора и от выбора дизайнеров. В нашем случае мы разработали очень общий пакет управления таблицами таблиц, потому что мы планировали (и использовали) один и тот же пакет для обработки нескольких языков (C, С++, Java, COBOL, несколько устаревших языков) единым способом. Однако абстрактные структуры пространств символов и наследования должны быть реализованы по существу эквивалентными способами для компиляторов С++; в конце концов, они должны моделировать ту же информацию. Я бы ожидал подобных структур в компиляторах GCC и Clang (ну, дуги наследования с целыми номерами, возможно, нет:)

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

Хотя создание синтаксического анализатора С++ очень сложно сам по себе, создание такой таблицы символов намного сложнее. Усилия затмевают усилия по созданию парсера С++. Наш преобразователь имен С++ - это 250K SLOC кода атрибута-грамматики, скомпилированный и исполняемый DMS. Получение прав на информацию - это огромная головная боль; Справочное руководство по С++ является огромным, запутанным, факты разбросаны по всему документу, и в разных местах это противоречиво (мы пытаемся отправить жалобы на это в комитет) и/или несовместимы между компиляторами (у нас есть версии для GCC и Visual Studio 201x).

Обновить март 2017: теперь есть таблицы символов для С++ 2014, причем С++ 2017 происходит на мгновение.

Ответ 2

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

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

Часть того, что вы говорите, не имеет смысла:

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

Как компилятор может определить, к какой конструкции относится имя, если он не может найти его в таблице символов?

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

Нет причин, по которым он не мог сделать это за один проход.

Я не мог понять, зависит ли это от компилятора или нет?

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

Я предполагал, что компилятор (для кода на С++) поместил бы имена функций с именами классов в таблицу, будь то одиночный или многопроходный компилятор. Как это зависит от проходов?

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

Кроме того, может ли кто-нибудь показать образец таблицы символов для простого класса С++, как бы он выглядел (имена функций с именем класса)?

Я дам ему удар:

class A
{
    int a;
    void f(int, int);
};

Приведёт таблицу символов, содержащую символы "A", "a" и "f". Обычно "a" и "f" будут отмечены областью, позволяющей упростить поиск, например:

"A"  -> (class)
"A::a"  ->  (class variable member)
"A::f(int,int)"  ->  (class function member)

Также возможно, что символы a и f не будут храниться в таблице символов верхнего уровня, а скорее, что каждое пространство имен (включая пространства и классы имен С++) будет иметь свою собственную таблицу символов, содержащую символы, определенные внутри него. Но это, возможно, просто выбор структуры данных. Вы можете абстрактно просматривать таблицу символов как плоскую таблицу, где имя сопоставляется с конструкцией.

В общем случае символ "A:: a" не будет выводиться в объектный файл, так как он не требуется для связывания.

Ответ 3

Короткий ответ: да, используя "nm --demangle" в linux

Длинный ответ: функции в таблице символов содержат имя функции плюс возвращаемое значение, и если оно принадлежит классу, это также имя класса. Но имена, типы (не всегда) и классы не написаны с полными именами, чтобы использовать меньше места. Эти строки называются demangle. Но вы знаете, что это короткое имя уникально, и вы можете разобрать полное имя класса из него. Чтобы просмотреть таблицу символов вашей программы, вы можете использовать "nm" в linux.

http://linux.about.com/library/cmd/blcmdl1_nm.htm

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