Внутренние имена
Функции, данные и объекты в программах на языках C и C++ внутренне представляются декорированными именами. Украшенное имя — это кодированная строка, созданная компилятором во время компиляции объекта, данных или определения функции. Оно содержит соглашения о вызовах, типы, параметры функции и другие сведения, а также имя. Это украшение имени, также известное как управление именами, помогает компоновщику найти правильные функции и объекты при связывании исполняемого файла.
Соглашения об именовании, украшенные, изменились в различных версиях Visual Studio, а также могут отличаться в разных целевых архитектурах. Чтобы правильно связаться с исходными файлами, созданными с помощью библиотек DLL и библиотек Visual Studio, C и C++, следует скомпилировать с помощью одного набора инструментов компилятора, флагов и целевой архитектуры.
Примечание.
Библиотеки, созданные Visual Studio 2015 или более поздней версии, могут использоваться приложениями, созданными с более поздними версиями Visual Studio до Visual Studio 2022. Дополнительные сведения см. в статье о совместимости двоичных файлов C++ между версиями Visual Studio.
Использование украшенных имен
Как правило, не нужно знать внутреннее имя, чтобы написать код, который успешно компилируется и компонуется. Внутренние имена — это внутренние средства для компилятора и компоновщика. Инструменты обычно могут обрабатывать имя в недекорированной форме. Тем не менее внутреннее имя иногда требуется при указании имени функции для компоновщика и других средств. Например, для сопоставления перегруженных функций C++, элементов пространств имен, конструкторов, деструкторов и специальных функций-членов класса, необходимо указать внутреннее имя. Дополнительные сведения о флагах и других ситуациях, требующих декорированных имен, см. в документации по средствам и параметрам, которые вы используете.
При изменении имени функции, класса, соглашении о вызовах, типа возвращаемого значения или какого-либо параметра внутреннее имя также изменяется. В этом случае необходимо получить новое внутреннее имя и использовать его везде, где оно указано.
Декорирование имен также важно при компоновке с кодом, написанным на других языках программирования, или при использовании других компиляторов. Разные компиляторы используют различные соглашения о дополнении имен. Если исполняемый файл связывается с кодом, написанным на другом языке, необходимо уделить особое внимание сопоставлению экспортированных и импортированных параметров и соглашений о вызовах. Код языка сборки должен использовать декорированные имена MSVC и соглашения о вызовах, чтобы связаться с исходным кодом, написанным с помощью MSVC.
Формат декорированного имени C++
Внутреннее имя функции C++ содержит следующие сведения.
имя функции.
Класс, в который входит функция, если это функция-член. Украшение может включать класс, который заключает класс, содержащий функцию, и т. д.
Пространство имен, к которому принадлежит функция, если она является частью пространства имен.
Типы параметров функции.
Соглашение о вызовах.
Тип значения, возвращаемого функцией.
Необязательный элемент целевого объекта. В ARM64EC объектах
$$h
тег вставляется в имя.
Имена функций и классов кодируются во внутреннем имени. Остальная часть внутреннего имени — это код, который имеет смысл только для компилятора и компоновщика. Ниже приведены примеры внешних и внутренних имен C++.
Внешнее имя | Внутреннее имя |
---|---|
int a(char){int i=3;return i;}; |
?a@@YAHD@Z |
void __stdcall b::c(float){}; |
?c@b@@AAGXM@Z |
Формат декорированного имени C
Формат декорирования для функции C зависит от соглашения о вызовах, используемого в ее объявлении, как показано в следующей таблице. Это также формат оформления, используемый при объявлении кода C++ для extern "C"
связывания. Соглашение о вызовах по умолчанию — __cdecl
. В 64-разрядной среде C или extern "C"
функции декорируются только при использовании соглашения о вызовах __vectorcall
.
Соглашение о вызовах | Оформление |
---|---|
__cdecl |
Ведущий подчеркивание (_ ) |
__stdcall |
Начальный символ подчеркивания () и конечный знак (_ @ ) и число байтов в списке параметров в десятичном разряде |
__fastcall |
Начальный и конечный знаки (@ ) с десятичным числом, представляющим число байтов в списке параметров |
__vectorcall |
Два конечных знака (@@ ), за которыми следует десятичное число байтов в списке параметров |
Для функций ARM64EC с компоновкой C (будь то компилированная как C или с помощью extern "C"
), она #
добавляется к декорированному имени.
Просмотр украшенных имен
Вы можете получить внутреннюю форму имени символа после компиляции исходного файла, содержащего данные, объект, определение или прототип функции. Для просмотра внутренних имен в программе можно использовать один из следующих методов.
Использование листинга для просмотра внутренних имен
Создайте список путем компиляции исходного файла, содержащего данные, объект или определение функции или прототип
/FA
с параметром компилятора (тип файла перечисления), заданным для сборки с исходным кодом (/FAs
).Например, введите
cl /c /FAs example.cpp
в командной строке разработчика, чтобы создать файл перечисления.example.asm
В результирующем файле перечисления найдите строку, которая начинается с
PUBLIC
и заканчивается точкой с запятой (;
), за которой следует неоцененные данные или имя функции. Символ междуPUBLIC
и точкой с запятой — это украшенное имя.
Использование служебной программы DUMPBIN для просмотра внутренних имен
Чтобы просмотреть экспортированные символы в OBJ или LIB-файле, введите
dumpbin /exports <obj-or-lib-file>
в командной строке разработчика.Чтобы найти внутреннюю форму символа, найдите внешнее имя в скобках. Декорированное имя находится в той же строке перед неоцененным именем.
Просмотр неоцененных имен
Можно использовать программу undname.exe для преобразования внутреннего имени в недекорированную форму. В этом примере показано, как это работает.
C:\>undname ?func1@a@@AAEXH@Z
Microsoft (R) C++ Name Undecorator
Copyright (C) Microsoft Corporation. All rights reserved.
Undecoration of :- "?func1@a@@AAEXH@Z"
is :- "private: void __thiscall a::func1(int)"
См. также
Дополнительные средства сборки MSVC
Использование extern
для указания компоновки