Vas*_*kin 6 c++ linker linker-errors visual-studio visual-c++
这是从我在将小型异常处理库集成到由单个 Visual Studio 解决方案中的约 200 个 Visual C++ 项目组成的代码库时遇到的一个看似小问题开始的。
我遇到了一个链接器问题,由这样的消息表示
3>B_Utils.lib(B_Utils.dll) : error LNK2005: "public: __cdecl ExceptionBase<class std::runtime_error>::ExceptionBase<class std::runtime_error>(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (??0?$ExceptionBase@Vruntime_error@std@@@@QEAA@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) already defined in TranslationUnit_2.obj
3>B_Utils.lib(B_Utils.dll) : error LNK2005: "public: virtual __cdecl ExceptionBase<class std::runtime_error>::~ExceptionBase<class std::runtime_error>(void)" (??1?$ExceptionBase@Vruntime_error@std@@@@UEAA@XZ) already defined in TranslationUnit_2.obj
3>B_Utils.lib(B_Utils.dll) : error LNK2005: "public: __cdecl ExceptionBase<class std::runtime_error>::ExceptionBase<class std::runtime_error>(class ExceptionBase<class std::runtime_error> const &)" (??0?$ExceptionBase@Vruntime_error@std@@@@QEAA@AEBV0@@Z) already defined in TranslationUnit_2.obj
Run Code Online (Sandbox Code Playgroud)
乍一看,它看起来是另一个典型的问题,可以通过典型的建议“尝试更改 #include 文件的顺序”或“将实现移出头文件”来解决,但事实并非如此。
我探索了许多类似的相关问题,例如this或this one,但没有一个适合我的情况。至少,建议的食谱对解决我的问题没有帮助。
此外,很早之前我们公司的人在迁移到VS2010的过程中遇到了另一个与Visual Studio链接器相关的问题,结果证明是链接器错误,请参见这里。无论如何,这都不符合我的情况。
所以这个小问题最终以整个小型研究告终。您可以在 github 上找到重现该问题的详细信息和玩具示例。同时,我将尝试尽可能简短地描述以下情况。
导致构建失败的关键因素是:
在代码中,它看起来像这样:
A_SDK:
(ExceptionBase.h)
template<typename T>
class ExceptionBase;
--
(foo.h)
#include "ExceptionBase.h"
inline void foo() // same effect would be with template<typename T> void foo()
{
throw ExceptionBase<std::runtime_error>("Problem");
}
Run Code Online (Sandbox Code Playgroud)
B_Utils:
(Error.h)
#include "ExceptionBase.h"
#if defined(B_EXPORTS)
#define _B_UTILS_EXPORTS_CLASS __declspec(dllexport)
#else
#define _B_UTILS_EXPORTS_CLASS __declspec(dllimport)
#endif
struct _B_UTILS_EXPORTS_CLASS Error : public ExceptionBase<std::runtime_error>
{ Error(std::string&& s); } // ctor definition is in *.cpp file
Run Code Online (Sandbox Code Playgroud)
C_客户端:
(TranslationUnit_1.cpp)
#include "A_SDK/foo.h"
#include "B_Utils/Error.h" // !!! Comment this line --> Build succeeds
void TranslationUnit_1() {
foo(); // !!! Comment this line --> Build succeeds
}
(TranslationUnit_2.cpp)
#include "A_SDK/foo.h"
void TranslationUnit_2() {
foo(); // !!! Comment this line --> Build succeeds
}
Run Code Online (Sandbox Code Playgroud)
注意那些标有 的行// !!!。评论其中任何一个都会使构建成功。如上所述,完整的源代码可以在 github 上找到。
谁能解释一下这里出了什么问题吗?本质上,我想了解:
PS 有一个解决方法可以帮助我推进我的工作。有关详细信息,请参阅github 的 README。然而,我仍然不清楚问题的根本原因。
Visual Studio 支持团队对这个问题进行了分类,并最终提交了一个错误。调查正在进行中,详细信息可以在 Visual Studio 论坛上查看。一旦收到他们的进一步反馈,我就会更新这个答案。
PS:无论这是否会被识别为链接器错误,我想声明的是,从 DLL 导出复杂的 C++ 接口通常并不是一个好的做法。不幸的是,我无法在我正在使用的代码库中更改它。
就我个人而言,对于基于 DLL 插件的架构,我建议要么使用一些编组层(如 COM),要么根据“沙漏原理”显式设计接口。以下是CppCon 2014 上的精彩演讲,解释了这是什么。
| 归档时间: |
|
| 查看次数: |
885 次 |
| 最近记录: |