Я искал различные посты относительно того, содержит ли таблица символов для кода C ++ имя функции наряду с именем класса. Что-то, что я мог найти в посте, это то, что это зависит от типа компилятора,
если он компилирует код за один проход, ему не нужно хранить имя класса и имена подпрограмм в таблице символов
но если это многопроходный компилятор, он может добавить информацию о классе (ах), с которыми он встречается, и их подпрограммах, чтобы он мог выполнять проверку типов аргументов и выдавать значимые сообщения об ошибках.
Я не мог понять, зависит ли это от компилятора или нет? Я предполагал, что компилятор (для кода C ++) поместит имена функций с именами классов в таблицу, будь то однопроходный или многопроходный компилятор. Как это зависит от пропусков? У меня нет такого большого / глубокого знания.
Кроме того, может ли кто-нибудь показать пример таблицы символов для простого класса C ++, как он будет выглядеть (имена функций с именем класса)?
Большинство учебников по компилятору расскажут вам о таблицах символов и часто показывают подробности о скромном языке сложности, таком как 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 ++ достигаются.
Обратите внимание, что имена классов записаны в (уникальном) глобальном пространстве имен, потому что они объявлены на верхнем уровне. Если бы они были определены в некотором явном пространстве имен, то пространство имен имело бы соответствующее собственное пространство символов, в котором записаны объявленные классы, а само пространство имен было бы записано в глобальном пространстве символов.
OP не спрашивал, как выглядит таблица символов для тел функций, но у меня просто есть иллюстративный слайд для этого, который тоже ниже.
Пространства символов работают одинаково. На этом слайде показана связь между пространством символов и областью области действия, которую он представляет. Эта связь фактически реализуется указателем, связанным с пространством символов, на соответствующий AST (определения пространства имен могут быть разбросаны по нескольким местам).
Обратите внимание, что в этом случае имя функции записывается в глобальном пространстве имен, потому что оно объявлено на верхнем уровне. Если бы оно было определено в области видимости класса, имя функции было бы записано в пространстве символов для тела класса (на предыдущей диаграмме).
Как правило, подробности от того, как организована таблица символов, полностью зависит от компилятора и выбора, который сделали дизайнеры. В нашем случае мы разработали очень общий пакет управления таблицей символов, поскольку планировали (и использовали) один и тот же пакет для обработки нескольких языков (C, C ++, Java, COBOL, нескольких устаревших языков) единообразным способом.
Однако абстрактные структуры символьных пространств и наследования должны быть реализованы по существу эквивалентными способами в компиляторах C ++; в конце концов, они должны моделировать ту же информацию. Я ожидаю, что подобные структуры в компиляторах GCC и Clang (ну, дуги наследования с целыми числами, возможно, нет 🙂
На практике не имеет значения, сколько «проходов» у вашего компилятора. Он должен построить эти структуры, чтобы вспомнить, что он знает о символах, в проход, и через проходы.
В то время как Создание синтаксического анализатора C ++ само по себе очень сложно, создать такую таблицу символов гораздо сложнее. Усилие затмевает усилия по созданию синтаксического анализатора C ++. Наш распознаватель имен C ++ представляет собой приблизительно 250K SLOC кода атрибута-грамматики, скомпилированного и выполненного DMS. Получение прав на детали — огромная головная боль; справочное руководство по C ++ огромно, запутанно, факты разбросаны по всему документу, а в разных местах оно противоречиво (мы пытаемся направить жалобы по этому поводу в комитет) и несовместимо между компиляторами (у нас есть версии для GCC и Visual Studio 201x).
Обновление март 2017: теперь есть таблицы символов для C ++ 2014.
Обновление от июня 2018 года: теперь есть таблицы символов для C ++ 2017.
Таблица символов отображает имена для конструкций внутри программы. Как таковой он используется для записи имен классов, функций, переменных и всего, что имеет заданное пользователем имя в программе.
(Существует два распространенных типа таблицы символов: один, который поддерживается компилятором при компиляции вашей программы, и другой, который существует в объектном файле, чтобы его можно было связать с другими объектами. Оба тесно связаны, но не обязательно должны иметь схожие внутреннее представление. Обычно только некоторые символы из таблицы символов компилятора будут выводиться в объект).
Часть того, что вы говорите, не имеет смысла:
если он компилирует код за один проход, ему не нужно хранить имя класса и имена подпрограмм в таблице символов
Как может компилятор определить, к какой конструкции относится имя, если он не может найти его в таблице символов?
но если это многопроходный компилятор, он может добавить информацию о классе (ах), с которыми он встречается, и их подпрограммах, чтобы он мог выполнять проверку типов аргументов и выдавать значимые сообщения об ошибках.
Нет причин, по которым он не мог сделать это за один проход.
Я не мог понять, зависит ли это от компилятора или нет?
Все компиляторы собираются использовать таблицу символов, но ее использование будет скрыто внутри реализации.
Я предполагал, что компилятор (для кода 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» не будет выводиться в объектный файл, поскольку он не требуется для компоновки.
Краткий ответ: да, используя ‘nm —demangle’ в Linux
Длинный ответ: функции в таблице символов содержат имя функции плюс возвращаемое значение и, если оно принадлежит классу, имя класса тоже. Но имена, типы (не всегда) и классы не пишутся с полными именами, чтобы использовать меньше места. Эта строка называется demangle. Но вы знаете, что это короткое имя уникально, и вы можете извлечь из него полное имя класса. Для просмотра таблицы символов вашей программы вы можете использовать ‘nm’ в linux.
http://linux.about.com/library/cmd/blcmdl1_nm.htm
Он получил флаг —demangle для просмотра оригинальных имен. Вы можете составить случайные короткие программы, чтобы увидеть, что получится.