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

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

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

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

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

4

Решение

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

Мы предлагаем полный интерфейс C ++ 14 для нашего инструментария реинжиниринга программного обеспечения DMS. Разбирает C ++, строит подробные ASTs, и выполняет разрешение имени и типа, которое включает в себя построение точной таблицы символов.

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

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

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

Таблица символов C ++: классовая перспектива

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

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

Таблица символов C ++: Перспектива функции

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

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

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

Обновление март 2017: теперь есть таблицы символов для C ++ 2014.
Обновление от июня 2018 года: теперь есть таблицы символов для C ++ 2017.

7

Другие решения

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

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

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

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

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

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

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

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

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

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

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

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

Я нанесу удар:

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 символы не будут храниться в таблице символов верхнего уровня, но вместо этого каждое пространство имен (включая пространства имен C ++ и классы) будет иметь свою собственную таблицу символов, содержащую символы, определенные внутри нее. Но это, пожалуй, просто выбор структуры данных. Вы по-прежнему можете абстрактно просматривать таблицу символов в виде плоской таблицы, где имя отображается в конструкции.

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

2

Краткий ответ: да, используя ‘nm —demangle’ в Linux

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

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

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

0
По вопросам рекламы [email protected]