1

我对这个错误感到疯狂,所以我认为一些更有经验的开发人员可以在这方面帮助我。我正在尝试编译一个使用 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()'的引用

是什么原因?当我在类方法中从外部库实例化一个类时,不会发生错误,但函数中的相同代码会产生链接器错误?(当我注释 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
4

2 回答 2

1

您的成员函数x::func1()永远不会在该编译单元(源文件)中使用 ODR 。大多数编译器只为类定义中定义的成员函数生成编译代码,前提是该成员函数在正在编译的编译单元中使用 ODR 。假设其他一些源文件确实使用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()

于 2013-09-04T10:23:18.153 回答
0

您应该链接到正确的库以修复您的链接(请参阅 Poco 文档以获取正确的链接)。

func1 具有外部链接,因此链接器需要 Poco::UUID 而 X::func1 是内联/私有/未使用的。

如果您使用static foo1()inline foo1()链接器错误消失如果您在错误链接器之外使用x::func1或实现x::func1class x{};

于 2013-09-04T10:33:23.307 回答