Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ambiguity of de-mangled C++ symbols

Tags:

c++

gcc

demangler

_ZNSaIwEC1Ev
_ZNSaIwEC2Ev

These two C++ symbols differ but are demangled (using C++filt or similar utility) into the same form:

std::allocator<wchar_t>::allocator()
std::allocator<wchar_t>::allocator()

Why so? Could it be a demangler's defect or what else?

like image 654
def Avatar asked Apr 13 '18 20:04

def


People also ask

Does C mangle name?

Since C is a programming language that does not support name function overloading, it does no name mangling. But for compilers targeted at Microsoft Windows Platform, which has a variety of calling conventions like _cdecl,_stdcall etc.

What is mangling and Demangling in C++?

That means that the C++ compiler needs to generate C identifier compatible symbols for C++ constructs. This process is called “mangling”, the resulting symbol is a “mangled symbol”, and reconstructing the original C++ name is “demangling”.

What is Demangling?

Demangling compiled C++ names with c++filt The c++filt utility is a filter that copies characters from file names or standard input to standard output, replacing all mangled names with their corresponding demangled names.

Is C++ name mangling standardized?

The C++ standard therefore does not attempt to standardize name mangling.


1 Answers

g++ uses the name mangling scheme (and other implementation details) specified by the Itanium ABI.

In the section on mangling of constructors and destructors, we see:

<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
  • The "complete object constructor" including C1 is the ordinary constructor directly used by initializations.
  • The "base object constructor" including C2 is used by a derived class constructor to initialize its base class subobject. This can be different from a "complete" constructor when virtual inheritance is involved, because only complete constructors initialize virtual bases, and base constructors instead assume their virtual bases have already been initialized.
  • The "complete object allocating constructor" including C3 presumably includes a call to operator new. But as far as I know, g++ never actually uses this one.
  • The "deleting destructor" including D0 finishes with a call to the appropriate scalar operator delete. This is necessary to tie to a virtual destructor because the correct operator delete might be a static class member which the base class knows nothing about.
  • The "complete object destructor" including D1 is like the reverse of the C1 constructor, and includes calls to destructors of virtual base classes.
  • The "base object destructor" including D2 is like the reverse of the C2 constructor, and omits calls to destructors of virtual base classes.

So the C1 and C2 pieces of the mangled names you asked about imply information which is important to the C++ system and must be correctly linked individually. But that information is difficult to briefly explain in a pseudo-code declaration, so the demangling function just describes both symbols identically.

Though since std::allocator<T> normally does not have any virtual base classes, it's likely that the two symbols actually point at the same code address, but g++ just provides both linker symbols for consistency.

like image 150
aschepler Avatar answered Sep 28 '22 08:09

aschepler