I am working on a project that is dependent on a third-party DLL. For reasons unknown, this DLL exports (most but not all) of the symbols for std::vector<unsigned char>
.
$ dumpbin.exe -exports Problem.lib | grep 'std::vector'
??0?$vector@EV?$allocator@E@std@@@std@@QEAA@$$QEAV01@@Z (public: __cdecl std::vector<unsigned char,class std::allocator<unsigned char> >::vector<unsigned char,class std::allocator<unsigned char> >(class std::vector<unsigned char,class std::allocator<unsigned char> > &&))
??0?$vector@EV?$allocator@E@std@@@std@@QEAA@$$QEAV01@AEBV?$allocator@E@1@@Z (public: __cdecl std::vector<unsigned char,class std::allocator<unsigned char> >::vector<unsigned char,class std::allocator<unsigned char> >(class std::vector<unsigned char,class std::allocator<unsigned char> > &&,class std::allocator<unsigned char> const &))
??0?$vector@EV?$allocator@E@std@@@std@@QEAA@AEBV01@@Z (public: __cdecl std::vector<unsigned char,class std::allocator<unsigned char> >::vector<unsigned char,class std::allocator<unsigned char> >(class std::vector<unsigned char,class std::allocator<unsigned char> > const &))
??0?$vector@EV?$allocator@E@std@@@std@@QEAA@AEBV01@AEBV?$allocator@E@1@@Z (public: __cdecl std::vector<unsigned char,class std::allocator<unsigned char> >::vector<unsigned char,class std::allocator<unsigned char> >(class std::vector<unsigned char,class std::allocator<unsigned char> > const &,class std::allocator<unsigned char> const &))
??0?$vector@EV?$allocator@E@std@@@std@@QEAA@AEBV?$allocator@E@1@@Z (public: __cdecl std::vector<unsigned char,class std::allocator<unsigned char> >::vector<unsigned char,class std::allocator<unsigned char> >(class std::allocator<unsigned char> const &))
??0?$vector@EV?$allocator@E@std@@@std@@QEAA@V?$initializer_list@E@1@AEBV?$allocator@E@1@@Z (public: __cdecl std::vector<unsigned char,class std::allocator<unsigned char> >::vector<unsigned char,class std::allocator<unsigned char> >(class std::initializer_list<unsigned char>,class std::allocator<unsigned char> const &))
??0?$vector@EV?$allocator@E@std@@@std@@QEAA@XZ (public: __cdecl std::vector<unsigned char,class std::allocator<unsigned char> >::vector<unsigned char,class std::allocator<unsigned char> >(void))
??0?$vector@EV?$allocator@E@std@@@std@@QEAA@_KAEBEAEBV?$allocator@E@1@@Z (public: __cdecl std::vector<unsigned char,class std::allocator<unsigned char> >::vector<unsigned char,class std::allocator<unsigned char> >(unsigned __int64,unsigned char const &,class std::allocator<unsigned char> const &))
??0?$vector@EV?$allocator@E@std@@@std@@QEAA@_KAEBV?$allocator@E@1@@Z (public: __cdecl std::vector<unsigned char,class std::allocator<unsigned char> >::vector<unsigned char,class std::allocator<unsigned char> >(unsigned __int64,class std::allocator<unsigned char> const &))
??1?$vector@EV?$allocator@E@std@@@std@@QEAA@XZ (public: __cdecl std::vector<unsigned char,class std::allocator<unsigned char> >::~vector<unsigned char,class std::allocator<unsigned char> >(void))
...
This means that if we attempt to use std::vector<unsigned char>
anywhere else in the codebase, the application will fail to link due to duplicate symbols:
Problem.lib(Problem.dll) : error LNK2005: "public: __cdecl std::vector<unsigned char,class std::allocator<unsigned char> >::~vector<unsigned char,class std::allocator<unsigned char> >(void)" (??1?$vector@EV?$allocator@E@std@@@std@@QEAA@XZ) already defined in Application.obj
Creating library C:UsersParkerprojectApplication.lib and object C:UsersParkerProjectApplication.exp
C:UsersParkerprojectApplication.exe : fatal error LNK1169: one or more multiply defined symbols found
I do not have the source code for this DLL and am unable to obtain a new version of it from the vendor. I have no reason to believe that these symbols were exported intentionally, but there is no chance of seeing this mistake fixed on the vendor’s end.
I have thought of a few potential workarounds for this issue:
- Modify the stub .lib to remove these symbols from the list of exported symbol. I have no idea if this can be done and have been unable to find the right search terms to figure that out.
- Use C++11’s
extern template
feature to try to just use the implementations in the DLL. This feels weird, as I’ve never seenextern template
used across a DLL boundary, and I don’t know if it is even supposed to work. My experiments thus far have been unsuccessful. - Just avoid using
std::vector<unsigned char>
entirely in application code. This feels extreme, but may actually require the least effort in the short term.
I realize this is an incredibly niche and stupid situation, but any guidance on potential workarounds would very much be appreciated.