Неоднозначность деформированных символов C++
_ZNSaIwEC1Ev
_ZNSaIwEC2Ev
Эти два символа C++ различаются, но разбиты (с использованием C++ Filter или аналогичной утилиты) в одну и ту же форму:
std::allocator<wchar_t>::allocator()
std::allocator<wchar_t>::allocator()
Почему так? Может ли это быть дефект деманглера или что-то еще?
1 ответ
В g++ используется схема искажения имени (и другие подробности реализации), определенные в Itanium ABI.
В разделе, касающемся искажения конструкторов и деструкторов, мы видим:
<ctor-dtor-name> ::= C1 # complete object constructor
::= C2 # base object constructor
::= C3 # complete object allocating constructor
::= D0 # deleting destructor
::= D1 # complete object destructor
::= D2 # base object destructor
- "Полный конструктор объекта", включая
C1
обычный конструктор, непосредственно используемый инициализацией - "Конструктор базовых объектов", включая
C2
используется конструктором производного класса для инициализации своего подобъекта базового класса. Это может отличаться от "полного" конструктора, когда задействовано виртуальное наследование, потому что только полные конструкторы инициализируют виртуальные базы, а конструкторы баз предполагают, что их виртуальные базы уже были инициализированы. - "Полный конструктор размещения объектов", включая
C3
предположительно включает в себя звонокoperator new
, Но, насколько я знаю, g++ на самом деле никогда не использует этот. - "Уничтожающий деструктор", включающий
D0
заканчивается звонком в соответствующий скалярoperator delete
, Это необходимо привязать к виртуальному деструктору, потому что правильныйoperator delete
может быть статическим членом класса, о котором базовый класс ничего не знает. - "Полный деструктор объекта", включая
D1
это как обратная сторонаC1
конструктор и включает вызовы деструкторов виртуальных базовых классов. - "Деструктор базового объекта", включая
D2
это как обратная сторонаC2
конструктор и пропускает вызовы деструкторов виртуальных базовых классов.
Итак C1
а также C2
части искаженных имен, о которых вы спрашивали, подразумевают информацию, которая важна для системы C++ и должна быть правильно привязана индивидуально. Но эту информацию сложно кратко объяснить в объявлении псевдокода, поэтому функция разборки просто описывает оба символа одинаково.
Хотя с тех пор std::allocator<T>
обычно не имеет никаких виртуальных базовых классов, вполне вероятно, что два символа фактически указывают на один и тот же кодовый адрес, но g++ просто обеспечивает оба символа компоновщика для согласованности.