12

I have a DLL one.dll that uses a class TwoClass exported from two.dll via class __declspec(dllexport). I'd like one.dll to use /delayload for two.dll, but I get a link error:

LINK : fatal error LNK1194: cannot delay-load 'two.dll' due to import
of data symbol '"__declspec(dllimport) const TwoClass::`vftable'"
(__imp_??_7TwoClass@@6B@)'; link without /DELAYLOAD:two.dll

That's in a Release build; in a Debug build it works. (I don't know what the difference is between Release and Debug in terms of vtable exports, nor can I find any compiler switches or pragmas to control it.)

How can I use /delayload with a DLL that exports classes like this in a Release build?

RichieHindle
  • 272,464
  • 47
  • 358
  • 399

4 Answers4

7

Have a look here, seems that the person had exactly the same problem and found a workaround

I managed to get the delay loading to work in release build by disabling the optimizations on the translation unit that was using SomeClass class - somehow it took away the dependency on exported vtable.

ZoogieZork
  • 11,215
  • 5
  • 45
  • 42
davka
  • 13,974
  • 11
  • 61
  • 86
  • 1
    The workaround there was to switch off optimisation, which does work but isn't ideal - I'd have to do it across a large subset of my code. If there were some way to control the specific optimisation that's affecting vtables, that would be great, but I can't find one. – RichieHindle Mar 08 '11 at 14:01
  • @RichieHindle - agree, that's why I didn't call it a solution:) – davka Mar 08 '11 at 14:04
  • 1
    It seems that this may be caused specifically by optimizations that require [adjuster thunks](http://blogs.msdn.com/b/oldnewthing/archive/2004/02/06/68695.aspx) - see also http://stackoverflow.com/questions/1090755/using-v-table-thunks-to-chain-procedure-calls (are the classes related by inheritance, specifically MI?) – MSalters Mar 08 '11 at 15:36
  • 2
    Setting `Remove unreferenced code and data` option to *No* allowed me to keep optimization enabled. [Reference](https://msdn.microsoft.com/en-us/library/dn642448.aspx?f=255&MSPPError=-2147217396) – notbad.jpeg May 18 '17 at 21:34
1

Check if one.dll contains a source file that includes TwoClass.hxx but does not actually use it. In addition check whether TwoClass meets the conditions for compiler generated methods (see conditions for automatic generation).

In my case I actually didn't need a compiler generated copy ctor nor the assignment operator for TwoClass so I declared them in the private: section without providing a definition. That created build errors for one.dll, which guided me to the source files that unnecessarily included TwoClass.hxx. After removing the unnecessary includes I was able to compile and link with optimization turned on and with /delayload.

I assume that the unnecessary #include statements misguided the optimizer to copy the compiler generated methods for TwoClass into the .obj files to be linked into one.dll even though they were not used in these .obj files. These unnecessary compiler generated methods for TwoClass seem to prevent a link with /delayload.

ThM
  • 31
  • 4
0

I had exactly same problem with class which contained inline implementation for exported class.

class __declspec(dllimport) VidExpInternal : public VidExpBase
{
public:
    VidExpInternal(TCHAR* msg=_T(""), int ln=__LINE__, TCHAR* filechar=_T(__FILE__)) :
        VidExpBase (msg,ln,filechar) {}

I've moved inline implementation to .cpp file - after that everything worked out smoothly.

class __declspec(dllimport) VidExpInternal : public VidExpBase
{
public:
    VidExpInternal(TCHAR* msg=_T(""), int ln=__LINE__, TCHAR* filechar=_T(__FILE__));
TarmoPikaro
  • 4,723
  • 2
  • 50
  • 62
0

Define a factory function that hands out instances of a class, much like in COM. This also requires that the interface(s) of the classes be public, but that's a given as well when someone imports a class.

0xC0000022L
  • 20,597
  • 9
  • 86
  • 152
  • 1
    Yep. Using `__declspec(dllexport)` on a class is a horrible idea, much better to expose the interface and let implementation details remain hidden inside the module. – Ben Voigt Mar 08 '11 at 13:58
  • this is a better style, but will this solve the OP problem with `delayload`? – davka Mar 08 '11 at 14:03
  • 1
    @davka: yes. The reason for this is simple to explain: you only export functions in this method, not data (which ultimately is the problem in delay-loading). – 0xC0000022L Mar 08 '11 at 14:07