Что такое имя mangling, и как это работает?

пожалуйста, объясните, что такое искажение имени, как оно работает, какую проблему оно решает, и в каких контекстах и языках используется. Стратегии искажения имен (например, какое имя выбрано компилятором и почему) плюс.

10 ответов


в языке программирования по вашему выбору, если идентификатор экспортируется из отдельно скомпилированного блока, ему нужно имя, по которому он известен во время ссылки. Имя коверкая решает проблему перегруженных идентификаторы в языках программирования. (Идентификатор "перегружается", если одно и то же имя используется в более чем одном контексте или с более чем одним значением.)

примеры:

  • в C++, функция или метод get может быть перегружен на нескольких типах.

  • в Ada или Modula-3, функция get может отображаться в нескольких модулях.

несколько типов и несколько модулей охватывают обычные контексты.

типичные стратегии:

  • сопоставьте каждый тип со строкой и используйте комбинированный идентификатор высокого уровня и "строку типа" в качестве имени времени связи. Распространено в C++ (особенно легко, поскольку перегрузка разрешена только для функции / методы и только для типов аргументов) и Ada (где вы также можете перегрузить типы результатов).

  • если идентификатор используется более чем в одном модуле или пространстве имен, присоедините имя модуля к имени идентификатора, например,List_get вместо List.get.

в зависимости от того, какие символы являются законными в именах времени ссылки, вам может потребоваться сделать дополнительное искажение; например, может потребоваться использовать подчеркивание как "побег" характер, так что вы можете различить

  • List_my.get ->List__my_get

С

  • List.my_get ->List_my__get

(по общему признанию, этот пример достигает, но как автор компилятора я должен гарантировать, что различные идентификаторы на карте исходного кода для различных имен времени ссылки. В этом вся причина и цель искажения имен.)


проще говоря, name-mangling-это процесс, с помощью которого компиляторы изменяют имена идентификаторов в исходном коде, чтобы помочь линкер при устранении неоднозначности между этими идентификаторами.

Википедия имеет замечательную статью на эту тему с несколькими отличными примерами.


имя коверкая - это средство, с помощью которого компиляторы изменяют "скомпилированное" имя объекта, чтобы сделать его отличным от того, что вы указали согласованным образом.

Это позволяет языку программирования гибко предоставлять одно и то же имя нескольким скомпилированным объектам и иметь согласованный способ поиска соответствующего объекта. Например, это позволяет нескольким классам с одинаковым именем существовать в разных пространствах имен (часто путем добавления пространства имен в имя класса и т. д.).

перегрузка оператора и метода во многих языках делает этот шаг дальше - каждый метод заканчивается "искаженным" именем в скомпилированной библиотеке, чтобы позволить нескольким методам на одном типе существовать с тем же именем.


в python name-mangling-это система, в которой переменные класса имеют разные имена внутри и вне класса. Программист "активирует" его, помещая два подчеркивания в начале имени переменной.

например, я могу определить простой класс с некоторыми членами:

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

в практике python имя переменной, начинающееся с подчеркивания, является "внутренним", а не частью интерфейса класса, поэтому программисты не должны полагаться на него. Тем не менее, это все еще видно:

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

имя переменной, начинающееся с двух подчеркиваний, по-прежнему является общедоступным, но оно искажено и, следовательно, сложнее получить доступ:

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

если мы знаем, как работает имя-искажение, однако, мы можем добраться до него:

>>> f._Foo__z
5

т. е. имя добавляется к имени переменной с дополнительным подчеркиванием.

Python не имеет понятия "частные" и "публичные" члены; все является публичным. Имя-искажение-самый сильный-возможный сигнал a программист может отправить, что переменная не должна быть доступна извне класса.


Source:http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html

Name mangling-это процесс, используемый компиляторами C++, который дает каждой функции в вашей программе уникальное имя. В C++, как правило, программы имеют по крайней мере несколько функций с одинаковым именем. Таким образом, искажение имен можно рассматривать как важный аспект в C++.

пример: Обычно имена членов однозначно генерируются объединение имени члена с именем класса, например, с учетом объявления:

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

val становится чем-то вроде:

  // a possible member name mangling
     val__11Class1

в Fortran имя mangling необходимо, потому что язык нечувствителен к регистру, что означает Foo, FOO, fOo, foo и т. д.. все будут разрешаться одним и тем же символом, имя которого должно быть каким-то образом нормализовано. Различные компиляторы реализуют искажение по-разному, и это является источником больших проблем при взаимодействии с C или двоичными объектами, скомпилированными с другим компилятором. GNU g77/g95, например, всегда добавляет завершающее подчеркивание к имени в нижнем регистре, если только имя уже не содержит одно или больше подчеркивает. В этом случае добавляются два подчеркивания.

например, следующая процедура

    program test
    end program 

    subroutine foo()
    end subroutine

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

создает следующие искореженные символы:

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

чтобы вызвать код Fortran из C, необходимо вызвать правильно искаженное имя подпрограммы (очевидно, учитывая возможные различные стратегии искажения, чтобы быть действительно независимым от компилятора). Чтобы вызвать код C из fortran, интерфейс c-written должен экспортировать правильно искаженные имена и вперед вызов в режим C. Затем этот интерфейс можно вызвать из Fortran.


большая часть объектно-ориентированного языка обеспечивает функцию перегрузки функции. Перегрузка Если какой-либо класс имеет несколько функций с одинаковыми именами, но разными типами и номерами параметров, они говорят, что они перегружены. Перегрузка функций позволяет использовать одно и то же имя для различных функций.

способы перегрузки функции

  1. путем изменения количества аргументов.
  2. пункт списка, имея различные типы аргументов.

как перегрузка функции достигается при искажении имени?
Компилятор C++ различает различные функции при создании объектного кода – он изменяет имена, добавляя информацию об аргументах на основе типа и количества аргументов. Этот метод добавления дополнительной информации к именам функций формы называется name Mangling. Стандарт C++ не указывает какой-либо конкретный метод для name искажение, поэтому разные компиляторы могут добавлять различную информацию к именам функций. Я запустил образец программы на 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;
}

эта программа имеет 3 функции с именем fun с различаются на основе количества аргументов и их типов. Эти имена функций искажены, как показано ниже:

ayadav@gateway1:~$ nm ./a.out |grep fun
000000000040058c W _ZN3ABC3funEff
00000000004005a0 W _ZN3ABC3funEif
000000000040057a W _ZN3ABC3funEll
  • ABC-это командная строка для имени класса
  • fun является общей строкой для имени функции
  • FF два поплавка - > F тип доводы
  • ll два длинных - >L тип аргументов
  • если первый целочисленный аргумент - >i и один float - >F аргумент

в то время, когда были разработаны Редакторы ссылок, такие языки, как C, FORTAN и COBOL, не имели пространств имен, классов, членов классов и других вещей. Искажение имен требуется для поддержки объектно-ориентированных функций, например, с редактором ссылок, который их не поддерживает. Тот факт, что редактор ссылок не поддерживает дополнительные функции, часто упускается; люди подразумевают это, говоря, что искажение имени требуется из-за редактора ссылок.

Так как есть так много различий между языковыми требованиями для поддержки того, что делает имя mangling, нет простого решения проблемы того, как поддерживать его в Редакторе ссылок. Редакторы ссылок предназначены для работы с выходными (объектными модулями) из различных компиляторов и поэтому должны иметь универсальный способ поддержки имен.


все предыдущие ответы верны, но вот перспектива/рассуждение Python с примером.

определение

когда переменная в классе имеет префикс _ _ (т. е. два подчеркивания) и не имеет суффикса _ _ (т. е. два подчеркивания или более), то она считается закрытым идентификатором. Интерпретатор Python преобразует любой частный идентификатор и его корежит, имя _класс__identfier

Example:
MyClassName --> _myClassName
__variable --> __variable

почему

этот необходимо, потому что во избежание проблем, которые могут быть вызваны переопределением атрибутов. Другими словами, для переопределения интерпретатор Python должен иметь возможность создавать отдельный идентификатор для дочернего метода по сравнению с родительским методом и использовать __ (двойное подчеркивание), чтобы python мог это сделать. В приведенном ниже примере без _ _ help этот код не будет работать.

class Parent:
    def __init__(self):
       self.__help("will take child to school")
    def help(self, activities):
        print("parent",activities)

    __help = help   # private copy of original help() method

class Child(Parent):
    def help(self, activities, days):   # notice this has 3 arguments and overrides the Parent.help()
        self.activities = activities
        self.days = days
        print ("child will do",self.activities, self.days)


# the goal was to extend and override the Parent class to list the child activities too
print ("list parent & child responsibilities")
c = Child()
c.help("laundry","Saturdays")

ответы здесь потрясающие, поэтому это просто дополнение из моего небольшого опыта: я использую имя, чтобы узнать, какие инструменты ( gcc / vs /...) и как параметры передаются в стек и с каким соглашением о вызовах я имею дело, и что основано на имени так, например, если см. _main Я знаю, что это Cdecl и другие