我对这个错误感到疯狂,所以我认为一些更有经验的开发人员可以在这方面帮助我。 我正在尝试编译一个使用C ++库(名为Poco)的示例项目。我的项目与已编译的poco库相关联。
以下是我的(最简化的)代码:
#include "Poco/UUID.h"
class x
{
void func1()
{
new Poco::UUID(); //A
}
};
void func1()
{
new Poco::UUID(); //B
}
现在编译上面的代码时,行'A'没有错误,但对于行'B'链接器说: 对'Poco :: UUID :: UUID()'
的未定义引用是什么原因?当我在类方法中从外部lib实例化一个类时没有发生错误但是函数中的相同代码会产生链接器错误? (当我对B行进行注释时,不会发生错误并生成链接器输出文件)
我的配置:Win7 / g ++ / CodeLite / MinGW-4.7.1
* 更新2: *谢谢。我的问题现在已经解决,问题是我使用MSVC编译器编译库,而我的应用程序是使用g ++编译的(都在Windows平台下)。所以我用g ++重新编译了库,现在一切正常。
更新1:这是我构建项目时的IDE输出:
C:\Windows\system32\cmd.exe /c "mingw32-make.exe -j 4 -e -f "dll1.mk" all"
----------Building project:[ dll1 - Debug ]----------
g++ -shared -fPIC -o ./Debug/dll1.so @"dll1.txt" -L. -Lc:/poco/lib -lPocoFoundationd
./Debug/PluginLibrary.o: In function `Z5func1v':
C:/Users/PARS/Documents/codelite/workspace1/dll1/PluginLibrary.cpp:12: undefined reference to `Poco::UUID::UUID()'
collect2.exe: error: ld returned 1 exit status
mingw32-make.exe: *** [Debug/dll1.so] Error 1
dll1.mk:77: recipe for target `Debug/dll1.so' failed
1 errors, 0 warnings
答案 0 :(得分:1)
您的成员函数x::func1()
在该编译单元(源文件)中永远不会使用ODR 。大多数编译器只为在类定义中定义的成员函数生成编译代码,如果该成员函数在正在编译的编译单元中是 ODR-used 。假设某些其他源文件确实使用x::func1()
。如果编译其他源文件,编译器将在目标文件中为与其他源文件对应的x::func1()
生成目标代码。
编译器可以绕过为x::func1()
生成编译代码的过程,因为类定义必须在所有编译单元中相同。如果编译其他具有不同类x定义的源文件,则违反了一个定义规则。这是未定义的行为,无需诊断。
如果没有源文件使用x::func1()
,那么你会发现一些永远不会被编译的死代码。代码有错误,但从未检测到。
编译器无法绕过为自由函数func1()
生成编译代码。该功能具有外部联动功能;编译器无法判断它是否可能在其他地方使用。编译器必须为该自由函数生成编译代码。
这是一个最低限度的工作示例:
class Missing {
public:
Missing();
int value;
};
class UsesMissing {
public:
int use_missing () {
Missing missing;
return missing.value;
}
int dont_use_missing () {
return 0;
}
};
#ifdef DEFINE_USE_MISSING
int use_missing () {
Missing missing;
return missing.value;
}
#endif
int main () {
UsesMissing test;
#ifdef USE_MISSING
return test.use_missing();
#else
return test.dont_use_missing();
#endif
}
编译时未定义DEFINE_USE_MISSING
或USE_MISSING
,这与g ++和clang ++编译和链接就好了。由于未定义的引用Missing::Missing()
,定义其中一个标志并且文件在链接步骤中失败。
答案 1 :(得分:0)
您应该链接到正确的库以修复您的链接(请参阅Poco文档以获取正确的链接)。
func1具有外部链接,因此链接器需要Poco :: UUID 而X :: func1是内联/私有/未使用。
如果使用static foo1()
或inline foo1()
,则链接器错误消失
如果您在x::func1
之外使用x::func1
或实现class x{};
,则会出现错误链接器