2009-08-22 20 views
38

Proszę wyjaśnić, czym jest wymazywanie nazwy, jak działa, jaki problem rozwiązuje oraz w jakich kontekstach i językach używa się. Strategie mieszania nazw (np. Nazwa wybrana przez kompilator i dlaczego) plus.Co to jest mangling nazw i jak to działa?

+3

Manglowane nazwy odegrały rolę w historii C++ dla koni trojańskich, zobacz: http://ejohnson.blogs.com/software/2004/11/i_find_c_intere.html – harpo

+1

@harpo: interesujące, ale trochę "ostre" ". Mam na myśli to, co zostało powiedziane, jest konsekwencją nowych funkcji. Nie sądzę, by w jakichkolwiek okolicznościach można było to uznać za celowe. –

Odpowiedz

35

W wybranym języku programowania, jeśli identyfikator jest eksportowany z osobno skompilowanej jednostki, potrzebuje nazwy, pod którą jest znana w czasie połączenia. Nazwa mangerowania rozwiązuje problem przeciążonych identyfikatorów w językach programowania. (Identyfikator jest „przeciążenia”, jeśli sama nazwa stosuje się więcej niż jednego związku lub więcej niż jeden sposób.)

kilka przykładów:

  • W C++, funkcja lub metoda get może być przeciążony w wielu typach.

  • W Ada lub Modula-3 funkcja get może występować w wielu modułach.

Wiele typów i wiele modułów obejmuje zwykłe konteksty.

Typowe strategie:

  • Mapa każdy typ na ciąg i użyć połączonej identyfikator wysokiego szczebla i „typ string” jako nazwę łącza czasu. Powszechne w C++ (szczególnie łatwe, ponieważ przeciążanie jest dozwolone tylko dla funkcji/metod i tylko dla typów argumentów) i Ada (gdzie można również przeciążać typy wyników).

  • Jeśli identyfikator jest używany w więcej niż jednym module lub przestrzeni nazw, należy połączyć nazwę modułu z nazwą identyfikatora, np. List_get zamiast List.get.

W zależności od tego, jakie znaki są poprawne w nazwach odsyłaczy, może być konieczne dodatkowe zniekształcenie; na przykład, może być konieczne użycie podkreślenia jako znak 'ucieczki', dzięki czemu można odróżnić

  • List_my.get ->List__my_get

z

  • List.my_get ->List_my__get

(Trzeba przyznać, że ten przykład sięga, ale jako pisarz kompilatora, muszę zagwarantować, że odrębne identyfikatory w mapie kodu źródłowego do różnych nazw czas łącza. To jest cały powód i cel mangerowania nazw.)

+0

Zmieszane imiona są zazwyczaj o wiele bardziej odrażające. Na przykład '__ZmlRK8Matrix3fRK3Ray' jest zmutowaną nazwą mojej funkcji o nazwie' operator Ray * (const Matrix3f & matrix, const Ray & oRay) '. Uwielbiam to, jak niektórzy nazywają to "dekoracją imienia". - Tak, poproszę, żeby moje nazwy funkcji zostały udekorowane, Blargh! – bobobobo

+0

Bardzo przydatna odpowiedź. Przykład "eskapowania" podkreśla w procesie mangowania nazw bardzo przydatnym dla kompilatorów źródło-źródło. – Askaga

4

Name mangling jest środkiem, za pomocą którego kompilatory modyfikują "skompilowaną" nazwę obiektu, aby uczynić go innym niż określony w spójny sposób.

Pozwala to językowi programowania na elastyczność polegającą na zapewnieniu tej samej nazwy wielu skompilowanym obiektom oraz na spójny sposób wyszukiwania odpowiedniego obiektu. Na przykład pozwala to na istnienie wielu klas o tej samej nazwie w różnych obszarach nazw (często poprzez dodanie przestrzeni nazw do nazwy klasy itp.).

Przeciążanie operatorów i metod w wielu językach idzie o krok dalej - każda metoda kończy się na "zniekształconej" nazwie w skompilowanej bibliotece, aby umożliwić istnienie wielu metod na jednym typie o tej samej nazwie.

2

W języku Python, mangling nazw jest systemem, w którym zmienne klasy mają różne nazwy wewnątrz i na zewnątrz klasy. Programista "aktywuje" go, umieszczając dwa podkreślenia na początku nazwy zmiennej.

Na przykład, można zdefiniować prostą klasę z niektórych członków:

>>> class Foo(object): 
... def __init__(self): 
... self.x = 3 
... self._y = 4 
... self.__z = 5 
... 

w praktyce Pythona, zmienna nazwa zaczynające się od znaku podkreślenia jest „wewnętrzną”, a nie częścią interfejsu klasy, a więc programiści nie należy na nim polegać. Jednak wciąż jest widoczny:

>>> f = Foo() 
>>> f.x 
3 
>>> f._y 
4 

Nazwa zmiennej rozpoczynając z dwoma podkreślenia jest jeszcze publiczna, ale jest to nazwa-zniekształcone, a tym samym trudniej dostępu:

>>> f.__z 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'Foo' object has no attribute '__z' 

Jeśli wiemy, jak sama nazwa -mangling prace, jednak możemy się na nią:

>>> f._Foo__z 
5 

czyli classname jest dołączany do nazwy zmiennej z dodatkowym podkreśleniem.

Python nie ma koncepcji "prywatnych" a "publicznych" członków; wszystko jest publiczne. Łamanie nazw jest najsilniejszym możliwym sygnałem, jaki programista może wysłać, aby zmienna nie była dostępna spoza klasy.

+0

należy zauważyć, że w python głównym powodem wymazywania nazw jest ["aby uniknąć zderzenia nazw nazw o nazwach określonych przez podklasy"] (https://docs.python.org/3/tutorial/classes.html) – dvb

0

W języku Fortran nazwa makr jest potrzebna, ponieważ w języku nie ma znaczenia wielkość liter, co oznacza, że ​​Foo, FOO, fOo, foo itd .. wszystkie rozwiążą ten sam symbol, którego nazwa musi być w jakiś sposób znormalizowana. Różne kompilatory implementują manewrowanie w różny sposób, a to jest źródłem ogromnych problemów podczas łączenia z C lub obiektami binarnymi skompilowanymi przy użyciu innego kompilatora. GNU g77/g95 na przykład zawsze dodaje końcowy znak podkreślenia do nazwy pisanej małymi literami, chyba że nazwa zawiera już jedno lub więcej podkreśleń. W tym przypadku dodawane są dwa podkreślenia.

Na przykład, następujące rutynowe

program test 
    end program 

    subroutine foo() 
    end subroutine 

    subroutine b_ar() 
    end subroutine 
    subroutine b_a_r() 
    end subroutine 

powstają następujące symbole zniekształcone:

0000000000400806 g  F .text 0000000000000006    b_ar__ 
0000000000400800 g  F .text 0000000000000006    foo_ 
000000000040080c g  F .text 0000000000000006    b_a_r__ 

W celu wywołania kod Fortran z C, odpowiednio zniekształcone rutynowe nazwa musi być użyty (oczywiście utrzymanie biorąc pod uwagę możliwe różne strategie manewrowania, aby być prawdziwie niezależnymi od kompilatora). Aby wywołać kod C z fortranu, interfejs napisany literą C musi odpowiednio eksportować zniekształcone nazwy i przekazywać wywołanie do procedury C. Interfejs ten można następnie wywołać z Fortran.

2

Źródło: http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html

Nazwa mangling jest procesem stosowanym przez kompilatory C++ dać każda funkcja w programie unikalną nazwę. W C++, ogólnie programy mają co najmniej kilka funkcji o tej samej nazwie. Zatem mangling nazw może być uważany za ważny aspekt w C++.

przykład: Powszechnie nazwy użytkownika są wyjątkowo wytwarzane przez łączenie nazwę członu z tym klasy np biorąc pod uwagę deklarację:

class Class1 
{ 
     public: 
      int val; 
      ... 
    }; 

val staje się czymś w rodzaju:

// a possible member name mangling 
    val__11Class1 
0

Większość z języka obiektowego zapewnić funkcję function przeciążenia. Funkcja Przeciążenie Jeśli jakakolwiek klasa ma wiele funkcji o tych samych nazwach, ale inne parametry mają numer &, to mówi się, że są przeciążone. Przeciążanie funkcji pozwala używać tej samej nazwy dla różnych funkcji.

Sposoby przeciążyć funkcję

  1. Zmieniając liczbę argumentów.
  2. Pozycja listy Posiadając różne typy argumentów.

W jaki sposób funkcja przeciążania jest osiągana w przypadku mangowania nazw? Kompilator C++ rozróżnia różne funkcje, gdy generuje kod obiektowy - zmienia nazwy, dodając informacje o argumentach na podstawie typu i liczby argumentów. Ta technika dodawania dodatkowych informacji w celu utworzenia nazw funkcji nosi nazwę Nazwa Mangling. Standard C++ nie określa żadnej konkretnej techniki wymazywania nazw, więc różne kompilatory mogą dołączać różne informacje do nazw funkcji. Uruchomiłem przykładowy program na gcc4.8.4.

class ABC 
{  
public: 
    void fun(long a, long b) {} 
    void fun(float a, float b) {} 
    void fun(int a, float b) {} 
}; 
int main() 
{ 
ABC obj; 
obj.fun(1l,2l); 
obj.fun(1,2.3f); 
obj.fun(3.2f,4.2f); 
return 0; 
} 

Ten program ma 3 funkcje o nazwie fun z różnymi na podstawie liczby argumentów i ich typów. Funkcje te nazwy są zniekształcone, jak poniżej:

[email protected]:~$ nm ./a.out |grep fun 
000000000040058c W _ZN3ABC3funEff 
00000000004005a0 W _ZN3ABC3funEif 
000000000040057a W _ZN3ABC3funEll 
  • ABC jest ciąg poleceń do nazwy klasy
  • zabawa jest wspólny ciąg dla nazwy funkcji
  • ff dwa float-> f rodzaj argumentów
  • Dwa długie argumenty typeof
  • jeśli pierwszy argument liczby całkowitej-> i i jeden argument float-> f
0

W czasie projektowania tych edytorów linków języki takie jak C, FORTAN i COBOL nie miały przestrzeni nazw, klas, elementów klas i innych tego typu rzeczy. Łamanie nazw jest wymagane do obsługi funkcji obiektowych, takich jak te z edytorem linków, które ich nie obsługują.Fakt, że edytor linków nie obsługuje dodatkowych funkcji, jest często pomijany; ludzie sugerują to, mówiąc, że wymuszanie nazwy jest wymagane ze względu na edytor linków.

Ponieważ istnieje wiele różnic między wymaganiami językowymi, które pomagają w tłumaczeniu nazw, nie ma prostego rozwiązania problemu, jak je obsługiwać w edytorze linków. Edytory linków są zaprojektowane do pracy z wyjściami (modułami obiektowymi) różnych kompilatorów i dlatego muszą mieć uniwersalny sposób obsługi nazw.