Wednesday, August 27, 2014

A hole in decorated C++ names

At the first glance Decorated C++ Names are ideal, they encode all possible C++ method names and allow links between .obj and .lib files. Read Format of a C++ Decorated Name.

But sometime these names can bring some mystics into your life. Today we spent plenty of time revealing a method of a one class doesn't work. It IS called, but you NEVER hit it. This became possible because there were TWO(!!) different classes of the same name.

Here is a prototype project reproducing such a case.



ClassA.h:
#include "Base.h"
class
ClassA : public Base
{
public:
   ClassA(void);
   int f(void);
};

ClassB.h:
#include "Base.h"
class
ClassA : public Base
{
public:
   ClassA(int a);
   int g(void);
};


The reason why compiler and linker produce no errors is because they have different Decorated C++ Names.
ClassA.obj:

?g@ClassA@@QAEHXZ (public: int __thiscall ClassA::g(void))
??0ClassA@@QAE@H@Z (public: __thiscall ClassA::ClassA(int))
??1ClassA@@QAE@XZ (public: __thiscall ClassA::~ClassA(void))

ClassB.obj:
?f@ClassA@@QAEHXZ (public: int __thiscall ClassA::f(void))
??0ClassA@@QAE@XZ (public: __thiscall ClassA::ClassA(void))
??1ClassA@@QAE@XZ (public: __thiscall ClassA::~ClassA(void))

Decorated Name of destructors are the same, but linker was surprisingly silent
(See Viewing Decorated Names for reference)




First of all download VS project here: Download
And here are main pieces of code to take a look at:

UserA.cpp:
#include "StdAfx.h"
#include "UserA.h"
#include "ClassA.h"

void UserA::Do()
{
   ClassA a;
}
UserB.cpp:
#include "StdAfx.h"
#include "UserB.h"
#include "ClassB.h"
void UserB::Do()
{
   ClassA b(1);
}
ClassAlreadyDefined.cpp:

#include "stdafx.h"
#include "UserA.h"
#include "UserB.h"


int _tmain(int argc, _TCHAR* argv[])
{
   UserA a;
   UserB b;
   a.Do();
   b.Do();

    return 0;
}

No comments:

Post a Comment