Nazwy ozdobione
Funkcje, dane i obiekty w programach C i C++ są reprezentowane wewnętrznie przez ich nazwy ozdobione. Nazwa ozdobiona to zakodowany ciąg utworzony przez kompilator podczas kompilacji obiektu, danych lub definicji funkcji. Rejestruje ona wywoływanie konwencji, typów, parametrów funkcji i innych informacji wraz z nazwą. Ta dekoracja nazwy, znana również jako mangling nazw, pomaga konsolidatorowi znaleźć poprawne funkcje i obiekty podczas łączenia pliku wykonywalnego.
Konwencje nazewnictwa ozdobione zostały zmienione w różnych wersjach programu Visual Studio i mogą być również różne w różnych architekturach docelowych. Aby poprawnie połączyć się z plikami źródłowymi utworzonymi przy użyciu programów Visual Studio, C i C++ DLL i bibliotek, należy skompilować przy użyciu tego samego zestawu narzędzi kompilatora, flag i architektury docelowej.
Uwaga
Biblioteki utworzone przez program Visual Studio 2015 lub nowszym mogą być używane przez aplikacje utworzone w nowszych wersjach programu Visual Studio za pośrednictwem programu Visual Studio 2022. Aby uzyskać więcej informacji, zobacz Zgodność binarna języka C++ między wersjami programu Visual Studio.
Używanie nazw ozdobionych
Zwykle nie musisz znać nazwy ozdobionej, aby napisać kod, który kompiluje i łączy się pomyślnie. Nazwy ozdobione są szczegółem implementacji wewnętrznym kompilatora i konsolidatora. Narzędzia zwykle obsługują nazwę w postaci nieukodowanej. Jednak nazwa ozdobiona jest czasami wymagana w przypadku określenia nazwy funkcji konsolidatora i innych narzędzi. Aby na przykład dopasować przeciążone funkcje języka C++, elementy członkowskie przestrzeni nazw, konstruktory klas, destruktory i specjalne funkcje składowe, należy określić nazwę ozdobioną. Aby uzyskać szczegółowe informacje o flagach opcji i innych sytuacjach, które wymagają nazw ozdobionych, zobacz dokumentację dotyczącą używanych narzędzi i opcji.
Jeśli zmienisz nazwę funkcji, klasę, konwencję wywoływania, typ zwracany lub dowolny parametr, nazwa ozdobiona również ulegnie zmianie. W takim przypadku należy uzyskać nową nazwę ozdobioną i używać jej wszędzie tam, gdzie jest określona nazwa ozdobiona.
Dekoracja nazw jest również ważna podczas łączenia z kodem napisanym w innych językach programowania lub przy użyciu innych kompilatorów. Różne kompilatory używają różnych konwencji dekoracji nazw. Gdy plik wykonywalny łączy się z kodem napisanym w innym języku, należy zachować szczególną ostrożność, aby dopasować wyeksportowane i zaimportowane nazwy oraz konwencje wywoływania. Kod języka zestawu musi używać nazw ozdobionych MSVC i konwencji wywoływania w celu połączenia z kodem źródłowym napisanym przy użyciu MSVC.
Format nazwy ozdobionej języka C++
Nazwa ozdobiona funkcji języka C++ zawiera następujące informacje:
Nazwa funkcji.
Klasa, do którego należy funkcja, jeśli jest funkcją składową. Dekoracja może zawierać klasę, która otacza klasę zawierającą funkcję itd.
Przestrzeń nazw, do którego należy funkcja, jeśli jest częścią przestrzeni nazw.
Typy parametrów funkcji.
Konwencja wywoływania.
Zwracany typ funkcji.
Opcjonalny element specyficzny dla elementu docelowego. W ARM64EC obiektach
$$h
tag jest wstawiany do nazwy.
Nazwy funkcji i klas są kodowane w nazwie ozdobionej. Pozostała część nazwy ozdobionej to kod, który ma znaczenie wewnętrzne tylko dla kompilatora i konsolidatora. Poniżej przedstawiono przykłady nieukodowanych i ozdobionych nazw języka C++.
Nazwa nieukodowana | Nazwa ozdobiona |
---|---|
int a(char){int i=3;return i;}; |
?a@@YAHD@Z |
void __stdcall b::c(float){}; |
?c@b@@AAGXM@Z |
Format nazwy ozdobionej języka C
Forma dekoracji dla funkcji języka C zależy od konwencji wywoływania używanej w jej deklaracji, jak pokazano w poniższej tabeli. Jest to również format dekoracji używany podczas deklarowanego extern "C"
powiązania kodu C++. Domyślna konwencja wywoływania to __cdecl
. W środowisku 64-bitowym język C lub extern "C"
funkcje są ozdobione tylko w przypadku korzystania z __vectorcall
konwencji wywoływania.
Konwencja wywoływania | Dekoracja |
---|---|
__cdecl |
Podkreślenie wiodące (_ ) |
__stdcall |
Wiodące podkreślenie () i znak końcowy (_ @ ), po którym następuje liczba bajtów na liście parametrów w liczbach dziesiętnych |
__fastcall |
Znaki wiodące i końcowe (@ ), po których następuje liczba dziesiętna reprezentująca liczbę bajtów na liście parametrów |
__vectorcall |
Dwa znaki końcowe (@@ ) i liczba dziesiętna bajtów na liście parametrów |
W przypadku funkcji ARM64EC z połączeniem języka C (czy skompilowanym jako C, czy przy użyciu extern "C"
), element #
jest poprzedzony nazwą ozdobioną.
Wyświetl nazwy ozdobione
Po skompilowaniu pliku źródłowego zawierającego dane, obiekt lub definicję funkcji lub prototyp można pobrać ozdobioną postać nazwy symbolu. Aby sprawdzić nazwy ozdobione w programie, można użyć jednej z następujących metod:
Aby wyświetlić nazwy ozdobione przy użyciu listy
Wygeneruj listę, kompilując plik źródłowy zawierający dane, obiekt lub definicję funkcji albo prototyp za pomocą
/FA
opcji kompilatora (Lista typu pliku) ustawioną na zestaw z kodem źródłowym (/FAs
).Na przykład wprowadź
cl /c /FAs example.cpp
w wierszu polecenia dewelopera, aby wygenerować plik listy,example.asm
.W wynikowym pliku listy znajdź wiersz rozpoczynający się od
PUBLIC
i kończy średnik (;
), po którym następuje nieukodowane dane lub nazwa funkcji. Symbol międzyPUBLIC
średnikiem to nazwa ozdobiona.
Aby wyświetlić nazwy ozdobione za pomocą narzędzia DUMPBIN
Aby wyświetlić wyeksportowane symbole w pliku OBJ lub LIB, wprowadź w
dumpbin /exports <obj-or-lib-file>
wierszu polecenia dewelopera.Aby znaleźć ozdobioną formę symbolu, poszukaj nazwy nieukodowanej w nawiasach. Nazwa ozdobiona znajduje się w tym samym wierszu, przed nazwą nieukodowaną.
Wyświetlanie nieukodowanych nazw
Możesz użyć undname.exe, aby przekonwertować nazwę ozdobioną na jej nieukodowaną formę. W tym przykładzie pokazano, jak to działa:
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)"
Zobacz też
Dodatkowe narzędzia kompilacji kompilatora MSVC
Używanie extern
do określania połączenia