Mangling jména - Name mangling
![]() | Tento článek má několik problémů. Prosím pomozte vylepši to nebo diskutovat o těchto problémech na internetu diskusní stránka. (Zjistěte, jak a kdy tyto zprávy ze šablony odebrat) (Zjistěte, jak a kdy odstranit tuto zprávu šablony)
|
v překladač konstrukce, zmanipulované jméno (také zvaný název dekorace) je technika používaná k řešení různých problémů způsobených nutností řešit jedinečné názvy programovacích entit v mnoha moderních programovací jazyky.
Poskytuje způsob kódování dalších informací ve jménu a funkce, struktura, třída nebo jiný datový typ za účelem předání více sémantických informací z překladač do linker.
Potřeba manglingu názvu vzniká tam, kde jazyk umožňuje pojmenovat různé entity stejným způsobem identifikátor pokud zabírají jinou jmenný prostor (obvykle definováno modulem, třídou nebo explicitní.) jmenný prostor směrnice) nebo mají různé podpisy (například v přetížení funkce ). V těchto případech použití je vyžadováno, protože každý podpis může vyžadovat jiné, specializované konvence volání ve strojovém kódu.
Žádný kód objektu vytvořený překladači je obvykle spojen s jinými částmi objektového kódu (vytvořeného stejným nebo jiným překladačem) typem programu, který se nazývá linker. Linker potřebuje velké množství informací o každé entitě programu. Například pro správné propojení funkce potřebuje její název, počet argumentů a jejich typů atd.
Jednoduché programovací jazyky 70. let C, pouze odlišil části kódu podle jejich názvu, ignoroval jakékoli další informace, jako jsou typy parametrů nebo návratové typy. Později programovací jazyky, jako C ++, definoval přísnější požadavky na části kódu, které mají být považovány za „rovnocenné“, jako jsou typy parametrů, návratový typ a konvence volání funkce. Tyto požadavky umožňují použití přetížení funkcí a také detekci různých chyb (například použití různých definic funkce pro kompilaci různých zdrojových souborů). Tyto přísnější požadavky potřebné pro práci s existujícími nástroji a konvencemi, proto byly v názvu zakódovány další požadavky symbolu, protože to byla jediná informace, kterou měl tradiční linker o symbolu.
Další použití manglingu názvu je detekce dalších změn nesouvisejících s podpisem, jako je čistota funkce nebo to, zda může potenciálně vyvolat výjimku nebo aktivovat uvolňování paměti. Příkladem jazyka, který to dělá, je D.[1][2] Jedná se spíše o zjednodušenou kontrolu chyb. Například funkce int f ();
a int g (int) čistý;
lze zkompilovat do jednoho souboru objektu, ale poté se jejich podpisy změnily na float f (); int g (int);
a slouží ke kompilaci jiného zdroje, který jej volá. V době propojení linker zjistí, že neexistuje žádná funkce f (int)
a vrátit chybu. Podobně linker nebude schopen detekovat návratový typ F
je jiný a vrátí chybu. V opačném případě by byly použity nekompatibilní konvence volání a pravděpodobně by došlo k nesprávnému výsledku nebo k havárii programu. Mangling obvykle nezachytí každý detail procesu volání. Například plně nezabrání chybám, jako jsou změny datových členů struktury nebo třídy. Například, struktura S {}; void f (S) {}
lze zkompilovat do jednoho souboru objektu, pak definice pro S
změněno na struct S {int x; };
a používá se při kompilaci volání f (S ())
. V takových případech kompilátor obvykle použije jinou konvenci volání, ale v obou případech F
změní název na stejný název, takže linker tento problém nezjistí a konečným výsledkem bude obvykle selhání nebo poškození dat nebo paměti za běhu.
Příklady
![]() | Tato sekce je napsán jako manuál nebo průvodce.Září 2016) (Zjistěte, jak a kdy odstranit tuto zprávu šablony) ( |
C
Ačkoli jazyky, které toto nepodporují, obecně nejsou vyžadovány nebo používány přetížení funkce, jako C a klasické Pascal, používají jej v některých případech k poskytnutí dalších informací o funkci. Například kompilátory zaměřené na platformy Microsoft Windows podporují různé konvence volání, které určují způsob, jakým jsou parametry odesílány do podprogramů a výsledky jsou vráceny. Protože různé konvence volání jsou navzájem nekompatibilní, kompilátoři manglují symboly s kódy podrobně popisujícími konvenci, která by se měla použít k volání konkrétní rutiny.
Manglingové schéma bylo založeno společností Microsoft a při kompilaci kódu pro platformy Windows ho neformálně následovali další kompilátoři, včetně Digital Mars, Borland a GNU GCC. Schéma se dokonce vztahuje i na jiné jazyky, například Pascal, D, Delphi, Fortran, a C#. To umožňuje podprogramům napsaným v těchto jazycích volat nebo být volány stávajícími knihovnami Windows pomocí konvence volání odlišné od jejich výchozí.
Při kompilaci následujících příkladů C:
int _cdecl F (int X) { vrátit se 0; }int _stdcall G (int y) { vrátit se 0; }int _fastcall h (int z) { vrátit se 0; }
32bitové kompilátory vydávají:
_f_g @ 4 @ h @ 4
V stdcall
a rychlé volání
mangling schémata, funkce je zakódována jako _název@X
a @název@X
respektive kde X je počet bajtů argumentů v seznamu parametrů v desítkové soustavě (včetně těch předaných v registrech, pro rychlé volání). V případě cdecl
, je název funkce pouze předponou podtržítka.
64bitová konvence v systému Windows (Microsoft C) nemá žádné podtržítko. Tento rozdíl může v některých ojedinělých případech vést k nevyřešeným externím stránkám při přenesení takového kódu na 64 bitů. Například Fortranský kód může použít alias k propojení s metodou C podle názvu takto:
PODPROGRAM F()! DEC $ PŘIKAZUJE C, ALIAS: '_ f' :: fKONEC PODPROGRAMU
Tím se kompiluje a propojí v pořádku pod 32 bitů, ale vygeneruje nevyřešený externí _F
pod 64 bitů. Jedním řešením tohoto problému je nepoužívat vůbec alias (ve kterém je třeba názvy metod obvykle psát velkými písmeny v C a Fortran). Další možností je použít volbu BIND:
PODPROGRAM F() SVÁZAT(C,NÁZEV="F")KONEC PODPROGRAMU
V jazyce C většina překladačů také manipuluje statické funkce a proměnné (a v C ++ funkcích a proměnných deklarovaných jako statické nebo vložené do anonymního oboru názvů) v překladových jednotkách pomocí stejných pravidel pro manipulaci jako pro jejich nestatické verze. Pokud jsou funkce se stejným názvem (a parametry pro C ++) také definovány a používány v různých překladových jednotkách, bude také změněno na stejný název, což může vést ke střetu. Nebudou však rovnocenné, pokud budou vyvolány v příslušných překladových jednotkách. Kompilátory obvykle mohou pro tyto funkce vydávat libovolné manglování, protože je nelegální k nim přistupovat přímo z jiných překladových jednotek, takže nikdy nebudou potřebovat propojení mezi různými objektovými kódy (jejich propojení nikdy není nutné). Aby se zabránilo konfliktům v propojení, kompilátoři použijí standardní mangling, ale budou používat takzvané „místní“ symboly. Při propojování mnoha takových překladových jednotek může existovat více definic funkce se stejným názvem, ale výsledný kód bude volat pouze jednu nebo druhou v závislosti na tom, z které překladové jednotky pochází. To se obvykle provádí pomocí přemístění mechanismus.
C ++
C ++ překladače jsou nejrozšířenějšími uživateli manglingu jmen. První překladače C ++ byly implementovány jako překladatelé do C zdrojový kód, který by pak byl kompilován kompilátorem C do objektového kódu; z tohoto důvodu musely názvy symbolů odpovídat pravidlům identifikátoru C. Dokonce později, s nástupem kompilátorů, kteří přímo produkovali strojový kód nebo montáž, je systém linker obecně nepodporoval symboly C ++ a mangling byl stále vyžadován.
The C ++ jazyk nedefinuje standardní schéma dekorace, takže každý kompilátor používá vlastní. C ++ má také složité jazykové funkce, jako je třídy, šablony, jmenné prostory, a přetížení operátora, které mění význam konkrétních symbolů na základě kontextu nebo použití. Meta-data o těchto funkcích mohou být disambiguated změnou (zdobení) název a symbol. Protože systémy pro úpravu názvů pro takové funkce nejsou standardizovány napříč kompilátory, může několik linkerů propojit kód objektu, který byl vytvořen různými kompilátory.
Jednoduchý příklad
Jedna překladová jednotka C ++ může definovat dvě pojmenované funkce F()
:
int F () { vrátit se 1; }int F (int) { vrátit se 0; }prázdnota G () { int i = F(), j = F(0); }
Jedná se o odlišné funkce bez vzájemného vztahu kromě jména. Kompilátor C ++ proto zakóduje informace o typu do názvu symbolu, výsledkem bude něco podobného:
int __F v () { vrátit se 1; }int __f_i (int) { vrátit se 0; } prázdnota __g_v () { int i = __F v(), j = __f_i(0); }
I když je jeho název jedinečný, G()
je stále rozbité: název rozdrobení se vztahuje na Všechno Symboly C ++ (ty, které nejsou v externí "C"{}
blok).
Složitý příklad
Manglované symboly v tomto příkladu v komentářích pod příslušným názvem identifikátoru jsou ty, které produkují překladače GNU GCC 3.x podle IA-64 (Itanium) ABI:
jmenný prostor wikipedia { třída článek { veřejnost: std::tětiva formát (); // = _ZN9wikipedia7article6formatEv bool print_to (std::ostream&); // = _ZN9wikipedia7article8print_toERSo třída wikilink { veřejnost: wikilink (std::tětiva konst& název); // = _ZN9wikipedia7article8wikilinkC1ERKSs }; };}
Všechny rozbité symboly začínají na _Z
(všimněte si, že identifikátor začínající podtržítkem následovaným velkým písmenem je a vyhrazený identifikátor v C, aby nedocházelo ke konfliktu s identifikátory uživatelů); u vnořených jmen (včetně obou jmenných prostorů a tříd) následuje N
, pak řada párů E
. Například, wikipedia :: article :: format
se stává:
_ZN9wikipedia7article6formatE
U funkcí potom následuje informace o typu; tak jako formát()
je prázdnota
funkce, to je jednoduše proti
; proto:
_ZN9wikipedia7article6formatEv
Pro print_to
, standardní typ std :: ostream
(což je typedef pro std :: basic_ostream
), který má speciální alias Tak
; odkaz na tento typ je tedy RSo
, přičemž celý název funkce je:
_ZN9wikipedia7article8print_toERSo
Jak různí překladači manipulují se stejnými funkcemi
Neexistuje standardizované schéma, podle kterého by byly rozbité i triviální identifikátory C ++, a proto různé kompilátory (nebo dokonce různé verze stejného kompilátoru nebo stejného kompilátoru na různých platformách) manipulují s veřejnými symboly radikálně odlišnými (a tedy naprosto nekompatibilními) způsoby. Zvažte, jak různé překladače C ++ manipulují se stejnými funkcemi:
Překladač | void h (int) | void h (int, char) | void h (void) |
---|---|---|---|
Intel C ++ 8.0 pro Linux | _Z1hi | _Z1hic | _Z1hv |
HP aC ++ A.05.55 IA-64 | |||
IAR EWARM C ++ 5.4 ARM | |||
GCC 3.X a vyšší | |||
Zvonit 1.X a vyšší[3] | |||
IAR EWARM C ++ 7.4 ARM | _Z <číslo> ahoj | _Z <číslo> hic | _Z <číslo> hv |
GCC 2.9.X | h__Fi | h__Fic | h__Fv |
HP aC ++ A.03.45 PA-RISC | |||
Microsoft Visual C ++ v6-v10 (manglingové detaily ) | ? h @@ YAXH @ Z | ? h @@ YAXHD @ Z | ? h @@ YAXXZ |
Digitální Mars C ++ | |||
Borland C ++ v3.1 | @ h $ qi | @ h $ qizc | @ h $ qv |
OpenVMS C ++ v6.5 (režim ARM) | H__XI | H__XIC | H__XV |
OpenVMS C ++ v6.5 (režim ANSI) | CXX $ __ 7H__FIC26CDH77 | CXX $ __ 7H__FV2CB06E8 | |
OpenVMS C ++ X7.1 IA-64 | CXX $ _Z1HI2DSQ26A | CXX $ _Z1HIC2NP3LI4 | CXX $ _Z1HV0BCA19V |
SunPro CC | __1cBh6Fi_v_ | __1cBh6Fic_v_ | __1cBh6F_v_ |
Tru64 C ++ v6.5 (režim ARM) | h__Xi | h__Xic | h__Xv |
Tru64 C ++ v6.5 (režim ANSI) | __7h__Fi | __7h__Fic | __7h__Fv |
Watcom C ++ 10.6 | W? H $ n (i) v | W? H $ n (ia) v | W? H $ n () v |
Poznámky:
- Kompilátor Compaq C ++ na OpenVMS VAX a Alpha (ale ne IA-64) a Tru64 má dvě schémata manglingu. Originální předstandardní schéma je známé jako model ARM a je založeno na změně názvu popsané v příručce C ++ Annotated Reference Manual (ARM). S příchodem nových funkcí ve standardním C ++, zejména šablony, schéma ARM se stávalo stále více nevhodným - nemohlo kódovat určité typy funkcí nebo produkovat identicky pozměněné názvy pro různé funkce. Proto byl nahrazen novějším modelem „ANSI“, který podporoval všechny funkce šablony ANSI, ale nebyl zpětně kompatibilní.
- Na IA-64 standard Aplikační binární rozhraní (ABI) existuje (viz externí odkazy ), který definuje (mimo jiné) standardní schéma úpravy názvu a kterou používají všichni kompilátoři IA-64. GNU GCC 3.X, navíc přijalo schéma úpravy názvu definované v této normě pro použití na jiných platformách jiných než Intel.
- Visual Studio a Windows SDK obsahují program
nepojmenovat
který vytiskne prototyp funkce ve stylu C pro dané rozbité jméno. - V systému Microsoft Windows, překladač Intel[4] a Zvonit[5] používá kompatibilitu názvu Visual C ++.
- Pro kompilátor IAR EWARM C ++ 7.4 ARM je nejlepším způsobem, jak určit název funkce, kompilace se zapnutým výstupem assembleru a pohled na výstup v takto vygenerovaném souboru „.s“.
Zpracování symbolů C při odkazování z C ++
Úkol společného idiomu C ++:
#ifdef __cplusplus externí "C" {#endif /* ... */#ifdef __cplusplus}#endif
je zajistit, aby symboly uvnitř byly „nezměněné“ - aby kompilátor vydával binární soubor s nedekorovanými jmény, jak by to dělal kompilátor C. Jelikož definice jazyka C jsou nezměněné, kompilátor C ++ se musí vyhnout změnám odkazů na tyto identifikátory.
Například standardní knihovna řetězců, <string.h>
, obvykle obsahuje něco podobného:
#ifdef __cplusplusexterní "C" {#endifprázdnota *pamětová sada (prázdnota *, int, size_t);char *strcat (char *, konst char *);int strcmp (konst char *, konst char *);char *strcpy (char *, konst char *);#ifdef __cplusplus}#endif
Kód, například:
-li (strcmp(argv[1], "-X") == 0) strcpy(A, argv[2]);jiný pamětová sada (A, 0, velikost(A));
používá správné, nezměněné strcmp
a pamětová sada
. Pokud externí "C"
nebyl použit, kompilátor (SunPro) C ++ by vytvořil kód ekvivalentní:
-li (__1cGstrcmp6Fpkc1_i_(argv[1], "-X") == 0) __1cGstrcpy6Fpcpkc_0_(A, argv[2]);jiný __1cGmemset6FpviI_0_ (A, 0, velikost(A));
Protože tyto symboly neexistují v běhové knihovně C (např. libc), došlo by k chybám odkazu.
Standardizovaný mangling názvu v C ++
Zdálo by se, že standardizované manglování názvu v jazyce C ++ by vedlo k větší interoperabilitě mezi implementacemi kompilátoru. Samotná taková standardizace by však nestačila k zajištění interoperability kompilátoru C ++ a mohla by dokonce vytvořit falešný dojem, že interoperabilita je možná a bezpečná, pokud není. Název mangling je jen jedním z několika binární rozhraní aplikace (ABI) podrobnosti, které je třeba rozhodnout a sledovat implementací C ++. Další aspekty ABI jako zpracování výjimek, virtuální tabulka rozložení, struktura a rám zásobníku polstrování, atd. také způsobí, že různé implementace C ++ budou nekompatibilní. Dále, vyžadování konkrétní formy manglování by způsobilo problémy pro systémy, kde implementační limity (např. Délka symbolů) diktují konkrétní manglingové schéma. Standardizovaný požadavek for name mangling would also prevent an implementation where mangling was not required vůbec - například linker that understand the C ++ language.
The C ++ standard proto se nepokouší standardizovat manipulaci se jmény. Naopak Anotovaná referenční příručka C ++ (také známý jako PAŽE, ISBN 0-201-51459-1, oddíl 7.2.1c) aktivně podporuje používání různých schémat manipulace, aby se zabránilo propojení, pokud jsou jiné aspekty ABI neslučitelné.
Nicméně, jak je podrobně uvedeno v části výše, na některých platformách[6] plné C ++ ABI bylo standardizováno, včetně manipulace se jmény.
Skutečné účinky změny názvu C ++
Protože symboly C ++ se běžně exportují z DLL a sdílený objekt soubory, schéma manipulace s názvy není pouze interní záležitostí kompilátoru. Různé překladače (nebo v mnoha případech různé verze stejného překladače) vytvářejí takové binární soubory pod různými schématy zdobení jmen, což znamená, že symboly jsou často nevyřešené, pokud kompilátory vytvářejí knihovnu a program, který ji používá, používá různá schémata. Například pokud si systém s více nainstalovanými kompilátory C ++ (např. GNU GCC a kompilátor dodavatele OS) přál nainstalovat Zvyšte knihovny C ++, muselo by to být kompilováno vícekrát (jednou pro GCC a jednou pro kompilátor dodavatele).
Z bezpečnostních důvodů je dobré, že kompilátoři produkující nekompatibilní kódy objektů (kódy založené na různých ABI, např. Třídách a výjimkách) používají různá schémata manipulace s názvy. To zaručuje, že tyto nekompatibility budou detekovány ve fázi propojení, nikoli při spuštění softwaru (což by mohlo vést k nejasným chybám a vážným problémům se stabilitou).
Z tohoto důvodu je zdobení jmen důležitým aspektem jakéhokoli jazyka C ++ ABI.
Demangle přes c ++ filtr
$ c ++ filt -n _ZNK3MapI10StringName3RefI8GDScriptE10ComparatorIS0_E16DefaultAllocatorE3hasERKS0_Map , Comparator , DefaultAllocator> :: has (StringName const &) const
Demangle prostřednictvím vestavěného GCC ABI
#zahrnout <stdio.h>#zahrnout <stdlib.h>#zahrnout <cxxabi.h>int hlavní() { konst char *mangled_name = „_ZNK3MapI10StringName3RefI8GDScriptE10ComparatorIS0_E16DefaultAllocatorE3hasERKS0_“; int postavení = -1; char *demangled_name = abi::__cxa_demangle(mangled_name, NULA, NULA, &postavení); printf("Demangled:% s n", demangled_name); volný, uvolnit(demangled_name); vrátit se 0;}
Výstup:
Demangled: Map , Comparator , DefaultAllocator> :: has (StringName const &) const
Jáva
V Javě je podpis metody nebo třídy obsahuje její název a typy jejích argumentů metody a případně návratovou hodnotu. Formát podpisů je zdokumentován, protože jazyk, kompilátor a formát souboru .class byly navrženy společně (a od začátku měly na mysli objektovou orientaci a univerzální interoperabilitu).
Vytváření jedinečných jmen pro vnitřní a anonymní třídy
Rozsah anonymních tříd je omezen na jejich nadřazenou třídu, takže kompilátor musí vytvořit „kvalifikovaný“ veřejný název pro vnitřní třídu, aby nedocházelo ke konfliktům, kde ve stejném oboru názvů existují další třídy se stejným názvem (vnitřním nebo nikoli). Podobně musí mít anonymní třídy pro ně vygenerované „falešné“ veřejné názvy (protože koncept anonymních tříd existuje pouze v kompilátoru, nikoli v modulu runtime). Kompilace následujícího programu Java
veřejnost třída foo { třída bar { veřejnost int X; } veřejnost prázdnota zark () { Objekt F = Nový Objekt () { veřejnost Tětiva toString() { vrátit se "Ahoj"; } }; }}
bude produkovat tři .třída soubory:
- foo.class, obsahující hlavní (vnější) třídu foo
- foo $ bar.classobsahující pojmenovanou vnitřní třídu foo.bar
- foo $ 1. třída, obsahující anonymní vnitřní třídu (local to method foo.zark)
Všechny tyto názvy tříd jsou platné (protože symboly $ jsou povoleny ve specifikaci JVM) a tyto názvy jsou „bezpečné“ pro generování kompilátoru, protože definice jazyka Java doporučuje nepoužívat symboly $ v normálních definicích tříd Java.
Rozlišení jmen v Javě je za běhu dále komplikováno plně kvalifikované názvy tříd jsou jedinečné pouze uvnitř konkrétního třídní nakladač instance. Classloadery jsou seřazeny hierarchicky a každé vlákno v JVM má takzvaný kontextový zavaděč tříd, takže v případech, kdy dvě různé instance třídy loadloader obsahují třídy se stejným názvem, se systém nejprve pokusí načíst třídu pomocí root (nebo systému) classloader a poté přejde hierarchií dolů do zavaděče tříd kontextu.
Nativní rozhraní Java
Podpora nativních metod Java umožňuje programům v jazyce Java volat programy napsané v jiném jazyce (obvykle C nebo C ++). Zde existují dva problémy s řešením názvů, z nichž žádný není implementován zvlášť standardním způsobem:
- Překlad JVM do nativního názvu - to se zdá být stabilnější, protože Oracle zveřejňuje své schéma.[7]
- Normální změna názvu v C ++ - viz výše.
Krajta
v Krajta, mangling se používá pro „soukromé“ členy třídy, kteří jsou označeni jako takoví, že jim dají jméno se dvěma předními podtržítky a ne více než jedním koncovým podtržítkem. Například, __věc
bude rozbité, stejně jako ___věc
a __věc_
, ale __věc__
a __věc___
nebude. Modul runtime Pythonu neomezuje přístup k těmto členům, manglování zabrání pouze kolizím jmen, pokud odvozená třída definuje člena se stejným názvem.
Když se setkáte s atributy pozměněnými jménem, Python transformuje tyto názvy přípravou jednoho podtržítka a názvu obklopující třídy, například:
>>> třída Test:... def __mangled_name(já):... složit... def normal_name(já):... složit>>> t = Test()>>> [attr pro attr v dir(t) -li "název" v attr]['_Test__mangled_name', 'normal_name']
Pascal
Řada Turbo Pascal / Delphi společnosti Borland
Abyste se vyhnuli změně názvu v Pascalu, použijte:
vývoz myFunc název 'myFunc', myProc název 'myProc';
Free Pascal
Free Pascal podporuje funkce a přetížení operátora, proto k podpoře těchto funkcí používá také mangling názvu. Na druhou stranu je Free Pascal schopen volat symboly definované v externích modulech vytvořených v jiném jazyce a exportovat vlastní symboly, aby byly volány jiným jazykem. Další informace najdete na stránce Kapitola 6.2 a 7.1 z Průvodce programátorem Pascal zdarma.
Fortran
Mangling jména je také nutný v Fortran překladače, původně proto, že jazyk je malá a velká písmena. Další požadavky na manglování byly uloženy později ve vývoji jazyka kvůli přidání moduly a další funkce ve standardu Fortran 90. Obzvláště řešení případů je častým problémem, který je třeba řešit, abychom mohli volat Fortranské knihovny, jako například LAPACK z jiných jazyků, například C.
Z důvodu necitlivosti na velká a malá písmena název podprogramu nebo funkce FOO
musí být převeden na standardizovaný případ a formát kompilátorem, aby byl propojen stejným způsobem bez ohledu na velikost písmen. Různí překladači to implementovali různými způsoby a nedošlo k žádné standardizaci. The AIX a HP-UX Fortranští překladači převádějí všechny identifikátory na malá písmena foo
, zatímco Cray a Unicos Fortran kompilátoři převedli identifikátory na všechna velká písmena FOO
. The GNU g77 překladač převede identifikátory na malá písmena a podtržítko foo_
, s výjimkou identifikátorů, které již obsahují podtržítko FOO_BAR
mít připojeny dvě podtržítka foo_bar__
v návaznosti na úmluvu stanovenou f2c. Mnoho dalších překladačů, včetně SGI je IRIX překladače, GNU Fortran, a Intel kompilátor Fortran (kromě systému Microsoft Windows), převést všechny identifikátory na malá písmena a podtržítko (foo_
a foo_bar_
). V systému Microsoft Windows má kompilátor Intel Fortran výchozí velká písmena bez podtržítka.[8]
Identifikátory v modulech Fortran 90 musí být dále zpracovány, protože v různých modulech může dojít ke stejnému názvu procedury. Jelikož standard Fortran 2003 vyžaduje, aby názvy procedur modulu nebyly v rozporu s jinými externími symboly,[9] kompilátoři mají tendenci používat název modulu a název procedury se zřetelnou značkou mezi nimi. Například:
modul m obsahujecelé číslo funkce Pět() Pět = 5 koncová funkce Pětkoncový modul m
V tomto modulu bude název funkce pozměněn jako __m_MOD_five
(např. GNU Fortran), m_MP_five_
(např. ifort společnosti Intel), m.five_
(např. Oracle's sun95) atd. Protože Fortran neumožňuje přetížení názvu procedury, ale používá obecné bloky rozhraní a místo toho obecné procedury vázané na typ, zmanipulované názvy nemusí obsahovat vodítka o argumentech.
Možnost Fortran 2003 BIND přepíše jakékoli manipulaci s názvem provedenou kompilátorem, jak je znázorněno výše.
Rez
![]() | Tato sekce potřebuje expanzi. Můžete pomoci přidávat k tomu. (Červen 2014) |
Názvy funkcí jsou ve výchozím nastavení rozbité Rez. To však může deaktivovat # [no_mangle]
atribut funkce. Tento atribut lze použít k exportu funkcí do C, C ++ nebo Objective-C.[10] Kromě toho spolu s #[Start]
atribut funkce nebo # [no_main]
atribut přepravky umožňuje uživateli definovat pro program vstupní bod ve stylu C.[11]
Rust použil mnoho verzí schémat manipulace se symboly, které lze vybrat v době kompilace pomocí -Z verze označující symbol
volba. Jsou definováni následující manglery:
dědictví
Manglování ve stylu C ++ na základě Itanium IA-64 C ++ ABI. Symboly začínají na_ZN
a pro disambiguaci se používají hashe souborů. Používá se od Rust 1.9.[12]v0
Vylepšená verze staršího schématu se změnami pro Rusta. Symboly začínají na_R
. Polymorfismus lze kódovat. Funkce nemají zakódované typy návratů (Rust nemá přetížení). Názvy Unicode se používají upravené punycode. Komprese (zpětná reference) používá bajtové adresování. Používá se od Rust 1.37.[13]
Příklady jsou uvedeny v Rust názvy symbolů
testy.[14]
Cíl-C
V zásadě existují dvě formy metody Cíl-C, třída („statická“) metoda a metoda instance. Deklarace metody v Objective-C má následující formu:
+ (návratový typ) název0:parametr0 název1:parametr1 ...– (návratový typ) název0:parametr0 název1:parametr1 ...
Metody třídy jsou označeny znakem +, metody instance používají -. Typická deklarace metody třídy pak může vypadat takto:
+ (id) initWithX: (int) číslo aY: (int) číslo;+ (id) Nový;
S instančními metodami, které vypadají takto:
- (id) hodnota;- (id) setValue: (id) new_value;
Každá z těchto deklarací metod má konkrétní interní reprezentaci. Při kompilaci je každá metoda pojmenována podle následujícího schématu pro metody třídy:
_C_Třída_název0_název1_ ...
a to například metody:
_i_Třída_název0_název1_ ...
Dvojtečky v syntaxi Objective-C jsou přeloženy do podtržítka. Metoda třídy Objective-C + (id) initWithX: (int) číslo aY: (int) číslo;
, pokud patří do Směřovat
třída by se přeložit jako _c_Point_initWithX_andY_
a metoda instance (patřící do stejné třídy) - (id) hodnota;
přeložit do _i_Point_value
.
Každá z metod třídy je označena tímto způsobem. Nicméně, aby bylo možné vyhledat metodu, na kterou může třída reagovat, bylo by únavné, kdyby byly všechny metody reprezentovány tímto způsobem. Každá z metod má přiřazen jedinečný symbol (například celé číslo). Takový symbol je znám jako volič. V Objective-C lze spravovat selektory přímo - mají specifický typ v Objective-C - SEL
.
Během kompilace je vytvořena tabulka, která mapuje textovou reprezentaci, například _i_Point_value
, k selektorům (kterým je zadán typ SEL
). Správa selektorů je efektivnější než manipulace s textovou reprezentací metody. Všimněte si, že selektor odpovídá pouze názvu metody, nikoli třídě, do které patří - různé třídy mohou mít různé implementace metody se stejným názvem. Z tohoto důvodu mají implementace metody také specifický identifikátor, tyto jsou známé jako ukazatele implementace a jsou také uvedeny typ, IMP
.
Odesílání zpráv je kódováno kompilátorem jako volání do id objc_msgOdeslat (id přijímač, SEL volič, ...)
funkce, nebo jeden z jejích bratranců, kde přijímač
je příjemcem zprávy a SEL
určuje způsob volání. Každá třída má vlastní tabulku, která mapuje selektory na jejich implementace - ukazatel implementace určuje, kde v paměti se nachází skutečná implementace metody. Pro metody třídy a instance existují samostatné tabulky. Kromě toho, že jsou uloženy v SEL
na IMP
vyhledávací tabulky, funkce jsou v zásadě anonymní.
The SEL
hodnota pro selektor se mezi třídami neliší. To umožňuje polymorfismus.
Modul runtime Objective-C udržuje informace o argumentech a návratových typech metod. Tyto informace však nejsou součástí názvu metody a mohou se u jednotlivých tříd lišit.
Protože Objective-C nepodporuje jmenné prostory, není třeba měnit názvy tříd (které se v generovaných binárních souborech zobrazují jako symboly).
Rychlý
Swift uchovává metadata o funkcích (a dalších) v pozměněných symbolech, které se na ně vztahují. Tato metadata zahrnují název funkce, atributy, název modulu, typy parametrů, návratový typ a další. Například:
Zmačkaný název metody func spočítat (x: int) -> int
a Moje třída
třída v modulu test
je _TFC4test7MyClass9calculatefS0_FT1xSi_Si
pro rok 2014 Swift. Složky a jejich význam jsou následující:[15]
_T
: Předpona pro všechny symboly Swift. Všechno to začne tím.F
: Non-curried funkce.C
: Funkce třídy. (metoda)4test
: Název modulu s předponou délky.7MyClass
: Název třídy, ke které funkce patří, opět s předponou délky.9 vypočítat
: Název funkce.F
: Atribut funkce. V tomto případě je to „f“, což je normální funkce.S0
: Určuje typ prvního parametru (jmenovitě instance třídy) jako první v zásobníku typů (zdeMoje třída
není vnořený a má tedy index 0)._FT
: Tím začíná seznam typů pro n-tici parametrů funkce.1x
: Externí název prvního parametru funkce.Si
: Označuje vestavěný typ Swift Šablona: Swift.Int pro první parametr._Si
: Návratový typ; znovu Šablona: Swift.Int.
Mangling pro verze od verze Swift 4.0 je oficiálně zdokumentována. Zachovává určitou podobnost s Itanium.[16]
Viz také
- Aplikační programovací rozhraní
- Binární rozhraní aplikace
- Konvence volání
- Porovnání aplikačních virtuálních strojů
- Rozhraní cizí funkce
- Nativní rozhraní Java
- Jazyková vazba
- Stropping
- LOK
Reference
- ^ "Aplikační binární rozhraní - programovací jazyk D". dlang.org. Citováno 2020-05-19.
- ^ Rainer, Schuetze. "D's Newfangled Name Mangling". Blog D. Citováno 2020-05-19.
- ^ Clang - Vlastnosti a cíle: Kompatibilita GCC, 15. dubna 2013
- ^ JBIntel_deleted_06032015. „OBJ rozdíly mezi Intel Compiler a VC Compiler“. software.intel.com.
- ^ "MSVC kompatibilita". Citováno 13. května 2016.
- ^ „Itanium C ++ ABI, Section 5.1 External Names (aka Mangling)“. Citováno 16. května 2016.
- ^ "Přehled designu". docs.oracle.com.
- ^ „Shrnutí problémů se smíšeným jazykem“. Uživatelská a referenční příručka pro Intel Fortran Compiler 15.0. Intel Corporation. Citováno 17. listopadu 2014.
- ^ https://software.intel.com/en-us/node/510637
- ^ "Rozhraní cizí funkce # Volání Rust kódu z C". Rust Manual. rust-lang.org. Citováno 13. května 2016.
- ^ „No stdlib“. Rust Manual. rust-lang.org. Citováno 13. května 2016.
- ^ "rust / src / librustc_codegen_utils / symbol_names / legacy.r.rs at 57e1da59cd0761330b4ea8d47b16340a78eeafa9 · rust-lang / rust · GitHub".
- ^ "Rust Symbol Mangling". Kniha Rust RFC.
- ^ "Rust 1.42.0: src / test / ui / symbol-names". Github. Citováno 20. března 2020.
- ^ „mikeash.com: Pátek Q&A 2014-08-15: Swift Name Mangling“. mikeash.com.
- ^ „apple / swift: mangling.rst“. GitHub.
externí odkazy
- Linux Itanium ABI pro C ++, včetně schématu rozbití názvu.
- Standardní specifikace Macintosh C / C ++ ABI
- c ++ filt - filtr pro demanglování kódovaných symbolů C ++ pro překladače GNU / Intel
- nepojmenovat - nástroj msvc k demanglování jmen.
- demangler.com - Online nástroj pro demangling symbolů GCC a MSVC C ++
- Runtime systém Objective-C - Od společnosti Apple Programovací jazyk Objective-C 1.0
- Konvence volání pro různé překladače C ++ podle Agner Fog obsahuje podrobný popis schémat manipulace s jmény pro různé překladače x86 a x64 C ++ (str. 24–42 ve verzi z 8. června 2011)
- Název C ++ Mangling / Demangling Docela podrobné vysvětlení schématu manipulace názvu kompilátoru Visual C ++
- PHP UnDecorateSymbolName php skript, který demangles názvy funkcí Microsoft Visual C.
- Míchání kódu C a C ++
- Levine, John R. (2000) [říjen 1999]. „Kapitola 5: Správa symbolů“. Linkery a nakladače. Řada Morgan Kaufmann v softwarovém inženýrství a programování (1. vyd.). San Francisco, USA: Morgan Kaufmann. ISBN 1-55860-496-0. OCLC 42413382. ISBN 978-1-55860-496-4. Archivováno z původního dne 2012-12-05. Citováno 2020-01-12. Kód: [1][2] Errata: [3]
- Jméno mangling demystifikováno Fivosem Kefallonitisem