CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6
  1. #1
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835

    Multiply defined symbols when linking to a DLL

    I'm building two DLLs - let's call them DLL_A and DLL_B. DLL_A builds as a standalone entity but DLL_B needs to link to the lib file for DLL_A (i.e. it imports some functionality from DLL_A). While linking DLL_B I see lots of errors taking the following form (bear in mind that port.cpp and port.h are source files in DLL_B:-

    DLL_A.lib(DLL_A.dll) : error LNK2005: "public: bool __thiscall std::vector<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > >::empty(void)const " (?empty@?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@std@@QBE_NXZ) already defined in port.obj
    I'm not sure if I'm reading that correctly but to me, it seems to be saying that some STL components are somehow getting exported from DLL_A (std::vector maybe?? Or std::string??) and that they conflict with similar objects already in port.obj. Sure enough, when I used dumpbin /EXPORTS on DLL_A there did seem to be some evidence that that was true. So my next step was to examine the source code for port.obj. Of course, strictly speaking I should be examining some code from DLL_A but it has hundreds of source modules so I figured that I should start by identifying whatever it is in DLL_B that's throwing up the conflict (since I at least know which module the conflict is in!).

    When I examined the source files for port.obj, std::string seems to get used quite often - but fortunately I could only find one occurrence of std::vector.

    In port.h it occurs here:-
    Code:
    class DLL_B_API Port : public boost::noncopyable
    {
    public:
    	// c'tors + d'tors
    
    
    	int get_connections (std::vector<std::string> &) const;
    
    	// rest of class
    
    };
    In port.cpp it occurs here:-
    Code:
    int Port::get_connections (std::vector<std::string> & c) const
    {
    	if (!port_engine.available()) {
    		c.insert (c.end(), _connections.begin(), _connections.end());
    		return c.size();
    	}
    
    	return port_engine.get_connections (_port_handle, c);
    }
    Is there anything in there that would be causing the above linker error? It's entirely possible that I'm looking in the wrong place but I suppose I've got to start somewhere....

    [Edit...] I just found a possible clue in one of the header files for DLL_A, where I found this class declaration:-

    Code:
    namespace PBD {
    
    class DLL_A_API Searchpath : public std::vector<std::string>
    {
    	// Whatever...
    };
    
    }
    Might that be causing std::vector<std::string> to get exported?
    Last edited by John E; October 24th, 2013 at 05:40 AM.
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  2. #2
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Multiply defined symbols when linking to a DLL

    By defining the export at the class level, you are effectively exporting the whole of searchpath including the dependants that are accessible.
    In the above case since you publicly derive SearchPath from std::vector, all public members from std::vector need to be exported as well or it would be impossible to do:
    Code:
    Searchpath p;
    p.empty();
    You've pretty much uncovered one of the cases where "lazy mode" exporting declspecs cause issues. And that is when you derive from a pure template class, then use that pure template class directly in a co-linked module.


    Solutions:
    1) make explicit overrides in Searchpath for each of the memberfunctions in std::vector (you could limit this to "any memberfunctions of std::vector you use in dll B"
    2) use private inheritance (I'm not 100% sure this will work in this particular case)
    3) don't derive searchpath from std::vector, make it a member of Searchpath instead
    4) export members instead of the whole class.

  3. #3
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835

    Re: Multiply defined symbols when linking to a DLL

    Thanks O'Reubens. I implemented your suggestion #4 and that fixed it. One question though... Here's how that class got declared in DLL_A:-

    Code:
    namespace PBD {
    
    class DLL_A_API Searchpath : public std::vector<std::string>
    {
    	// Whatever...
    };
    
    }
    Shouldn't namespace PBD be helping me here? When I used dumpbin /EXPORTS to examine the DLL, all the various functions from class Searchpath were in namespace PBD - but the base class wasn't. Obviously, 'vector' and 'string' were in namespace std but it's definitely possible for namespaces to be nested - so why wasn't the base class effectively PBD::std::vector<std::string>
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  4. #4
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Multiply defined symbols when linking to a DLL

    Quote Originally Posted by John E View Post
    so why wasn't the base class effectively PBD::std::vector<std::string>
    Because there is no such class as PDB::std::vector<std::string>. The vector is in namespace std -- you can't attach it onto a "third-party" namespace and make it now myNamespace::std::vector.

    Regards,

    Paul McKenzie

  5. #5
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835

    Re: Multiply defined symbols when linking to a DLL

    That makes sense Paul. Thanks.
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  6. #6
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Multiply defined symbols when linking to a DLL

    don't have a compiler handy atm so can't test... but wouldn't
    Code:
    namespace PDB
    {
    #include <vector>
    }
    cause the vector to be PDB::std::vector<> ?

    can't say I can find a good reason to do so for vector, but wrapping your own namespace around an include has been usefull at times to force a 3rd party header into a namespace to solve name colisions.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured