【问题标题】:c++ undefined references with static libraryc++ 带有静态库的未定义引用
【发布时间】:2011-02-07 03:07:02
【问题描述】:

我正在尝试从一个类中创建一个静态库,但是在尝试使用它时,我总是会遇到任何未定义引用的错误。我进行的方式是创建像

这样的目标文件
g++ -c myClass.cpp -o myClass.o

然后用

打包
ar rcs myClass.lib myClass.o

我显然通常缺少一些东西。我敢打赌这是带有符号的东西。 感谢您的任何建议,我知道如果阅读一些教程,我很可能会发现它很抱歉,如果再次打扰愚蠢的东西:)

编辑:

myClass.h:

class myClass{
    public:
        myClass();
        void function();
};

myClass.cpp:

#include "myClass.h"

myClass::myClass(){}
void myClass::function(){}

使用类的程序:

#include "myClass.h"

int main(){
myClass mc;
mc.function();

return 0;
}

最后我是这样编译的:

g++ -o main.exe -L. -l myClass main.cpp

这个错误很经典:

C:\Users\RULERO~1\AppData\Local\Temp/ccwM3vLy.o:main.cpp:(.text+0x31): undefined
 reference to `myClass::myClass()'
C:\Users\RULERO~1\AppData\Local\Temp/ccwM3vLy.o:main.cpp:(.text+0x3c): undefined
 reference to `myClass::function()'
collect2: ld returned 1 exit status

【问题讨论】:

标签: c++ static-libraries


【解决方案1】:

用途:

g++ -o main.exe main.cpp myClass.lib 

使用库路径和 -l 标志充满问题,但如果必须这样做,请将库重命名为 libmylib.a,然后编译为:

g++ -o main.exe main.cpp -L. -lmylib 

另请注意,出于可移植性的原因,在源文件或输出文件的名称中使用混合大小写通常不是一个好主意。

【讨论】:

  • 是的,我听说过库的推荐名称。但我已经发现如果无法链接库,错误看起来会有所不同。所以我会说这不是这种情况下的解决方案.你不必犹豫叫我笨蛋白痴;)
  • 我总是忘记链接顺序对 g++ 很重要 - 每次 :-(
【解决方案2】:

可能是一个链接顺序问题。当 GNU 链接器看到一个库时,它会丢弃所有不需要的符号。在这种情况下,您的库出现在您的 .cpp 文件之前,因此在编译 .cpp 文件之前该库被丢弃。这样做:

g++ -o main.exe main.cpp -L. -lmylib

g++ -o main.exe main.cpp myClass.lib

Microsoft 链接器不考虑命令行中库的顺序。

【讨论】:

  • 不要。这会吸引各种开发人员。我可能花了一周的时间试图找出一个大型项目中奇怪的链接器问题,结果就是这个问题。
  • 你是我今天的英雄! :) 我花了一个小时坐在一个未定义的引用链接器错误前,才发现这是一个简单的错误。非常感谢:)
  • 非常感谢,刚刚遇到这个线程有同样的问题,它也为我解决了这个问题! :)
  • 即使在 linux 下的 cmake 框架中,似乎 target_link_libraries() 中的顺序也很重要。非常感谢您的指示,为我节省了很多时间!
  • 即使在 2015 年下半年,这仍然是高度相关的!
【解决方案3】:

这应该避免链接错误并创建 .so 共享库:

LOCAL_ALLOW_UNDEFINED_SYMBOLS := true

【讨论】:

  • 这不只是将问题推迟到运行时吗?
【解决方案4】:

另一个可能的原因:忘记extern "C"

我遇到了这个问题,因为我试图将 C++ 程序与 C 静态库链接。库的标头没有extern "C",因此链接器正在寻找一个损坏的函数名,而库实际上具有未损坏的函数名。

花了一段时间才弄清楚发生了什么,所以我希望这对其他人有所帮助。

【讨论】:

  • 谢谢,这为我节省了很多时间
【解决方案5】:

这是链接器如何优化输出代码的问题。 假设我们有一个使用两个库的可执行文件:Lib_ALib_BLib_A 依赖于 Lib_B Lib_A 定义符号:Lib_A1Lib_A2Lib_B 定义符号 Lib_B1Lib_B2。 现在假设可执行文件仅使用符号 Lib_A1,而 Lib_A1 使用在 Lib_B 中定义的符号 Lib_B1。符号 Lib_B1 从未在可执行文件中使用。

  1. 在 Windows 的情况下,链接器的工作方式如下:我有两个可执行文件,其中使用了一些库和可执行文件中使用的所有符号,所有库都是 lib_A1lib_B1 .因此,我将需要这两个符号,其余的都是不必要的。我将取消定义 lib_A2lib_B2
  2. 在 linux 的情况下,如果您在 Lib_A 之前链接 Lib_B,如下所示: g++ .... -lLib_B -lLib_A 链接器的工作方式如下:我有一个可执行文件,它首先链接 Lib_B。我没有看到可执行文件使用符号 Lib_B1Lib_B2。它们是不必要的,因此我将取消定义它们。后来链接器看到了。哦,我还有另一个库 Lib_A。我可以看到可执行文件使用符号 Lib_B1。我将保留它并取消定义未使用的符号 Lib_B2。它没有看到 Lib_B1 使用 Lib_A1,它已经未定义。
  3. 在 linux 的情况下,如果您在 Lib_B 之前链接 Lib_A,如下所示: g++ ... -lLib_A -lLib_B 链接器的工作方式如下:我有一个可执行文件,它首先链接 Lib_A。哦,我可以看到可执行文件使用 Lib_A1。我将保留它们并取消定义 Lib_A2。以后就可以看到了。哦,我还有另一个库 Lib_B。我可以看到现在带有已链接符号的可执行文件,使用 Lib_B1,我将保留它们。因此它保留了 Lib_B1Lib_A1,以及未定义的 Lib_B2Lib_A2

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-24
    • 1970-01-01
    • 1970-01-01
    • 2016-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多