1

ALL,

I have a static link library which exports a class. This class contains a member of std::mutex.

When I link this library to my main project there is no problem, but when I try to link the library to dynamic link library in the same project I'm getting the undefined external symbol.

I double check and all the libraries I link are the same.

Whats weird is that the linker complain about the member and not the class itself.

What could be the issue?

TIA!

P.S. if it matter - I'm working with msvc 2017 on Windows 8.1.

P.P.S.:

Command to build the application:

/GS /analyze- /W4 /Zc:wchar_t /I"C:\Program Files (x86)\Visual Leak Detector\include" /I"..\dbinterface" /I"..\libdbwindow\res\gui" /I"c:\wxWidgets\lib\vc_dll\mswud" /I"c:\wxWidgets\include" /I"." /I"C:\Program Files (x86)\Visual Leak Detector\include" /Zi /Gm- /Od /Fd"vc_mswuddll\docview.pdb" /Zc:inline /fp:precise /D "WIN32" /D "_DEBUG" /D "_CRT_SECURE_NO_DEPRECATE=1" /D "_CRT_NON_CONFORMING_SWPRINTFS=1" /D "_SCL_SECURE_NO_WARNINGS=1" /D "WXMSW" /D "_UNICODE" /D "WXUSINGDLL" /D "_WINDOWS" /D "NOPCH" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /Oy- /MDd /FC /Fa"vc_mswuddll" /EHsc /nologo /Fo"vc_mswuddll\docview" /Fp"vc_mswuddll\docview.pch" /diagnostics:classic

Command to build the library:

/GS /analyze- /W4 /Zc:wchar_t /I"C:\Program Files (x86)\Visual Leak Detector\include" /I"..\dbinterface" /I"..\libfieldswindow" /I"..\libshapeframework" /I"..\libpropertypages" /I"..\libpropertieshandlers" /I"c:\wxWidgets\lib\vc_dll\mswud" /I"c:\wxWidgets\include" /I"." /Zi /Gm- /Od /Fd"vc_mswuddll\tabledataedit.pdb" /Zc:inline /fp:precise /D "MEMORYLEAKS" /D "WIN32" /D "_USRDLL" /D "DLL_EXPORTS" /D "_DEBUG" /D "_CRT_SECURE_NO_DEPRECATE=1" /D "_CRT_NON_CONFORMING_SWPRINTFS=1" /D "_SCL_SECURE_NO_WARNINGS=1" /D "WXMSW" /D "_UNICODE" /D "WXUSINGDLL" /D "MY_DLL_BUILDING" /D "_WINDLL" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /RTC1 /GR /Gd /Oy- /MDd /FC /Fa"vc_mswuddll" /EHsc /nologo /Fo"vc_mswuddll" /Fp"vc_mswuddll\tabledataedit.pch" /diagnostics:classic

The symbol is declared as

class __declspec(dllexport) Database
{
protected:
    struct Impl;
    Impl *pimpl;
    // more members here
};

struct Database::Impl
{
    static std::mutex my_mutex;
    // more members here
};

EDIT:

c:\Users\Igor\OneDrive\Documents\dbhandler_app\dbhandler\Debug>dumpbin /symbols
dbinterface.lib
Microsoft (R) COFF/PE Dumper Version 14.16.27045.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file dbinterface.lib

File Type: LIBRARY

COFF SYMBOL TABLE
000 010569A5 ABS    notype       Static       | @comp.id
001 80000191 ABS    notype       Static       | @feat.00
002 00000000 SECT1  notype       Static       | .drectve
    Section length   41, #relocs    0, #linenums    0, checksum        0
    Relocation CRC 00000000
005 00000000 SECT2  notype       Static       | .debug$S
    Section length 23FC, #relocs    2, #linenums    0, checksum        0
    Relocation CRC 3EE39AC2
008 00000000 SECT3  notype       Static       | .debug$T
    Section length   70, #relocs    0, #linenums    0, checksum        0
    Relocation CRC 00000000
00B 00000000 SECT4  notype       Static       | .bss
    Section length    4, #relocs    0, #linenums    0, checksum        0, select
ion    2 (pick any)
    Relocation CRC 00000000
00E 00000000 SECT4  notype       External     | ___@@_PchSym_@00@UfhvihUrtliUlmv
wirevUwlxfnvmghUwyszmwoviPzkkUwyrmgviuzxvUwvyftUhgwzucOlyq@4B2008FD98C1DD4
00F 00000000 SECT5  notype       Static       | .msvcjmc
    Section length    1, #relocs    0, #linenums    0, checksum 77073096
    Relocation CRC 00000000
012 00000000 SECT5  notype       Static       | __BDBDE527_dbinterface@pch
013 00000000 SECT6  notype       Static       | .debug$S
    Section length   84, #relocs    2, #linenums    0, checksum        0, select
ion    5 (pick associative Section 0x4)
    Relocation CRC 4D9779EE
016 00000000 SECT7  notype       Static       | .chks64
    Section length   38, #relocs    0, #linenums    0, checksum        0
    Relocation CRC 00000000

String Table Size = 0x8A bytes

  Summary

           4 .bss
          38 .chks64
        2480 .debug$S
          70 .debug$T
          41 .drectve
           1 .msvcjmc

EDIT 1:

Link command for application:

/OUT:"vc_mswuddll\docview.exe" /MANIFEST /NXCOMPAT /PDB:"vc_mswuddll\docview.pdb" /DYNAMICBASE "vld.lib" "dbinterface.lib" "wxmsw31ud_core.lib" "wxbase31ud.lib" "wxtiffd.lib" "wxjpegd.lib" "wxpngd.lib" "wxzlibd.lib" "wxregexud.lib" "wxexpatd.lib" "kernel32.lib" "user32.lib" "gdi32.lib" "comdlg32.lib" "winspool.lib" "winmm.lib" "shell32.lib" "shlwapi.lib" "comctl32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "rpcrt4.lib" "advapi32.lib" "version.lib" "wsock32.lib" "wininet.lib" "odbc32.lib" "odbccp32.lib" /DEBUG /MACHINE:X86 /SAFESEH /INCREMENTAL /PGD:"vc_mswuddll\docview.pgd" /SUBSYSTEM:WINDOWS /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"vc_mswuddll\docview.exe.intermediate.manifest" /ERRORREPORT:PROMPT /NOLOGO /LIBPATH:"C:\Program Files (x86)\Visual Leak Detector\lib\Win32" /LIBPATH:".\Debug" /LIBPATH:"c:\wxWidgets\lib\vc_dll" /TLBID:1

Link command for the dynamic library:

/OUT:"..\dbhandler\vc_mswuddll\tabledataedit.dll" /MANIFEST /NXCOMPAT /PDB:"vc_mswuddll\tabledataedit.pdb" /DYNAMICBASE "vld.lib" "dbinterface.lib" "fieldswindow.lib" "shapeframework.lib" "propertieshandlers.lib" "propertypages.lib" "wxmsw31ud_adv.lib" "wxmsw31ud_core.lib" "wxbase31ud.lib" "wxtiffd.lib" "wxjpegd.lib" "wxpngd.lib" "wxzlibd.lib" "wxregexud.lib" "wxexpatd.lib" "kernel32.lib" "user32.lib" "gdi32.lib" "comdlg32.lib" "winspool.lib" "winmm.lib" "shell32.lib" "shlwapi.lib" "comctl32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "rpcrt4.lib" "advapi32.lib" "version.lib" "wsock32.lib" "wininet.lib" "odbc32.lib" "odbccp32.lib" /IMPLIB:"vc_mswuddll\tabledataedit.lib" /DEBUG /DLL /MACHINE:X86 /SAFESEH /INCREMENTAL /PGD:"vc_mswuddll\tabledataedit.pgd" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"vc_mswuddll\tabledataedit.dll.intermediate.manifest" /ERRORREPORT:PROMPT /NOLOGO /LIBPATH:"C:\Program Files (x86)\Visual Leak Detector\lib\Win32" /LIBPATH:"..\dbhandler\Debug" /LIBPATH:"..\libfieldswindow\vc_mswuddll" /LIBPATH:"..\libshapeframework\vc_mswuddll" /LIBPATH:"..\libpropertieshandlers\vc_mswuddll" /LIBPATH:"..\libpropertypages\vc_mswuddll" /LIBPATH:"c:\wxWidgets\lib\vc_dll" /TLBID:1

EDIT:

And here is the result of dumpbin with the change:

c:\Users\Igor\OneDrive\Documents\dbhandler_app\dbhandler\Debug>dumpbin /symbols
dbinterface.lib
Microsoft (R) COFF/PE Dumper Version 14.16.27045.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file dbinterface.lib

File Type: LIBRARY

COFF SYMBOL TABLE
000 010569A5 ABS    notype       Static       | @comp.id
001 80000191 ABS    notype       Static       | @feat.00
002 00000000 SECT1  notype       Static       | .drectve
    Section length   41, #relocs    0, #linenums    0, checksum        0
    Relocation CRC 00000000
005 00000000 SECT2  notype       Static       | .debug$S
    Section length 23FC, #relocs    2, #linenums    0, checksum        0
    Relocation CRC 3EE39AC2
008 00000000 SECT3  notype       Static       | .debug$T
    Section length   70, #relocs    0, #linenums    0, checksum        0
    Relocation CRC 00000000
00B 00000000 SECT4  notype       Static       | .bss
    Section length    4, #relocs    0, #linenums    0, checksum        0, select
ion    2 (pick any)
    Relocation CRC 00000000
00E 00000000 SECT4  notype       External     | ___@@_PchSym_@00@UfhvihUrtliUlmv
wirevUwlxfnvmghUwyszmwoviPzkkUwyrmgviuzxvUwvyftUhgwzucOlyq@4B2008FD98C1DD4
00F 00000000 SECT5  notype       Static       | .msvcjmc
    Section length    1, #relocs    0, #linenums    0, checksum 77073096
    Relocation CRC 00000000
012 00000000 SECT5  notype       Static       | __BDBDE527_dbinterface@pch
013 00000000 SECT6  notype       Static       | .debug$S
    Section length   84, #relocs    2, #linenums    0, checksum        0, select
ion    5 (pick associative Section 0x4)
    Relocation CRC 4D9779EE
016 00000000 SECT7  notype       Static       | .chks64
    Section length   38, #relocs    0, #linenums    0, checksum        0
    Relocation CRC 00000000

String Table Size = 0x8A bytes

  Summary

           4 .bss
          38 .chks64
        2480 .debug$S
          70 .debug$T
          41 .drectve
           1 .msvcjmc
Igor
  • 5,620
  • 11
  • 51
  • 103

1 Answers1

0

__declspec(dllexport) means the question is about an import library of a DLL (not a "static link library"), and in that case the error is due to my_mutex not being exported. This could be resolved by exporting:

  • either the entire nested class;

    struct __declspec(dllexport) Database::Impl
    {
      static std::mutex my_mutex;
      // more members here
    };
    
  • or just the static variable in question.

    struct Database::Impl
    {
      static __declspec(dllexport) std::mutex my_mutex;
      // more members here
    };
    

This should work for the std::mutex used in the example here, but will run into C4251 with other STL templatized classes. That, in turn, can be worked around (see One way of eliminating C4251 warning when using stl-classes in the dll-interface for example), but a better solution might be to rearrange the APIs so that my_mutex does not need to be exported to begin with.

dxiv
  • 16,984
  • 2
  • 27
  • 49
  • both libraries use /MDd switch. And both libraries do not use `/GL' option. Anything else to check – Igor Feb 24 '21 at 03:28
  • @Igor Were both build with the same version of the toolset (compiler, libraries etc), and does either link to any third library that also uses the VC++ libraries? Does the error occur in the non-debug/release `/MD` build, too? Also, it would help narrow it down if you posted the exact version of the toolset and the symbol(s) reported as unresolved. – dxiv Feb 24 '21 at 04:35
  • everything is built using MSVC 2017 Community. I also added project options MSVC uses to compile both application and the dynamic library. Im not there yet to try the release build Symbol reported is `public: static class std::mutex Database::Impl::my_mutex` – Igor Feb 24 '21 at 04:57
  • @Igor That's only the `cl` compile line, but the `link` one would be of interest, too. Does "*command to build the library*" refer to the dynamic library which fails to link, or to the library that exports the class? Also, if you look at the `.lib` file that exports the class with `dumpbin` at a VC developer cmd prompt (`dumpbin /symbols` for a static library, or `dumpbin /exports` for an import library), does it list `Database::Impl::my_mutex`? – dxiv Feb 24 '21 at 05:15
  • @Igor Now that it turned out it's about an import library, I am pretty sure the answer to the `dumpbin /exports` question must be negative, so I updated the answer accordingly. – dxiv Feb 24 '21 at 06:41
  • I updated an OP with the results of `dumpbin /symbols`. But what I don't understand is - why my executable project compiles and links fine. – Igor Feb 24 '21 at 07:22
  • @Igor Assuming you link the same `.lib` in the two cases, it must be that the .exe doesn't reference the mutex variable, while the .dll does. Why and how exactly that happens can't be second-guessed without a reproducible example. – dxiv Feb 24 '21 at 07:36
  • I added link commands for both - application and the library that fails. Do you see anything wrong? – Igor Feb 24 '21 at 07:46
  • @Igor The way you have it now `Database::Impl::my_mutex` is not exported from the DLL, and no linker command can magically fix that. You can get it to work using either choice from my answer. But if you want to figure out *why* the symbol gets referenced at all, then you'll have to dig deeper into those sources, listings and mapfiles that we can't see. – dxiv Feb 24 '21 at 07:58
  • I added __declspec(dllexport) to the struct declaration, but I'm still getting the same error. – Igor Feb 25 '21 at 07:06
  • I also added the results of dumpbin with the change to the OP. And so the question still stands - why it fails only on the DLL? – Igor Feb 25 '21 at 07:12
  • @Igor This latest `dumpbin` is literally identical to the one you posted yesterday, and still does not list `my_mutex` among the symbols. Don't know whether it's a miscompile or whatever else, and honestly I can't help beyond this point unless you post a minimal, self-contained example that reproduces the issue. – dxiv Feb 25 '21 at 07:20