It is All about Traffic, and Programming
Search
Archives
0 visitors online now
0 guests, 0 members

The Move Constructor: A Linking Pitfall of Qt Library with Different Compilers

This post has already been read 395 times!

Move constructor is a C++11 feature from ISO/IEC14882:2011.  It enhanced the old-school C++ copy constructor by moving the resource of an object, instead of member-wise copying.  It is faster than a copy constructor.  Thus a C++11 compiler will generate six special member functions for a C++ object, including  move constructor and move assignment operator:

  • Default Constructor
  • Copy Constructor
  • Copy Assignment Operator
  • Destructor
  • Move Constructor
  • Move Assignment Operator

We are not going to discuss C++11 Move Constructor in details here –  better details and better explanations are there, and there.

The motivation of  this article,  is not to discuss the semantics or usage of Move Constructor,  but an interesting debugging experience, and the lessons learned which involves C++11 move constructor.

Long story short – I have been working on developing an advanced Qt-based C++ plugin DLL for a host software developed in Qt 4.8.7.   I was using Visual C++ 2010 compiler, and the Qt for VS2010 official release for commercial applications.

The plugin DLL is supposed to be dynamically loaded by the host via Qt’s QLibrary API (see my previous article on this subject), which internally will call Microsoft’s Win32 API LoadLibrary.  Somehow, I got the following error, when trying to load the DLL into the host software:

34f8:3518 @ 01570140 – LdrpGetProcedureAddress – INFO: Locating procedure “AcdssPluginFactory” by name
34f8:3518 @ 01570140 – LdrpNameToOrdinal – WARNING: Procedure “AcdssPluginFactory” could not be located in DLL at base 0x0B630000
34f8:3518 @ 01570140 – LdrpReportError – WARNING: Locating export “AcdssPluginFactory” for DLL “Unknown” failed with status: 0xc0000139
34f8:1168 @ 01570265 – LdrpReportError – ERROR: Locating export “??4QString@@QAEAAV0@$$QAV0@@Z” for DLL “C:\Program Files (x86)\…\plugins\acdssplugin.DLL” failed with status: 0xc0000139

The above debug messages were generated by GFlags Utility, which comes with Debugging Tools for Windows. You can find the most advanced debugging techniques including how to use GFlags utility from the excellent book Inside Windows Debugging.  In our case, we just need to set “Show Loader Snaps” flag, as shown in the figure.  This is a typical way of debugging LoadLibrary failures.

2016-10-12_21-41-26

Looking at the debug messages, it is simply pointing out that LoadLibrary fails because an exported function is missing from the image space – its C++ mangled name as  “??4QString@@QAEAAV0@$$QAV0@@Z”,  which can be interpreted as:


    ? = C++ mangled symbol
    ?4 = "operator="
    QString@ = the enclosing class, hence method name: QString::operator=
    @ = end of the scope
    Q = public
    A = no const and volatile qualifier
    E = __thiscall
    AAV0 = const ref to the first named class (QString) - the return value (const QString &)
    @ = end return type
    $$ = move constructor &&
    QAV0 = const pointer to first named class - QString * const
    @ = end parameter type
    @ = end parameters
    Z = function

So clearly, the host software was complaining that the Move Constructor of QString can not be located in any of the image space.  Upon further inspection of the host software, it is discovered it was compiled using VS2005.  QtCore4.dll does not have the Move Constructor generated with VC++ 2005 compiler.  

The solution is simple – just rebuilt the Qt 4.8.7 using VC++ 2005, and rebuilt the plugin DLL.  Above all, the lessons learned are:

Do NOT mix Qt library compiled with different compilers, EVEN with the same Qt Version.  Period.

This post has already been read 395 times!

Leave a Reply

Your email address will not be published. Required fields are marked *