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 Dekoracji
__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

  1. 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.

  2. 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ędzy PUBLIC średnikiem to nazwa ozdobiona.

Aby wyświetlić nazwy ozdobione za pomocą narzędzia DUMPBIN

  1. Aby wyświetlić wyeksportowane symbole w pliku OBJ lub LIB, wprowadź w dumpbin /exports <obj-or-lib-file> wierszu polecenia dewelopera.

  2. 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