zoukankan      html  css  js  c++  java
  • "undefined reference to" 问题解决方法

    最近在 Linux 下编程发现一个诡异的现象,就是在链接一个静态库的时候总是报错,类似下面这样的错误:

    (.text+0x13): undefined reference to `func’

    关于undefined reference 这样的问题,大家其实经常会遇到,在此,我以详细地示例给出常见错误的各种原因以及解决方法,希望对初学者有所帮助。

    1. 链接时缺失了相关目标文件(.o)
    测试代码如下:
    测试代码
    然后编译。

    gcc -c test.c
    gcc –c main.c

    得到两个 .o 文件,一个是 main.o,一个是 test.o ,然后我们链接 .o 得到可执行程序:

    gcc -o main main.o

    这时,你会发现,报错了:

    main.o: In function `main’:
    main.c:(.text+0x7): undefined reference to ‘test’
    collect2: ld returned 1 exit status

    这就是最典型的 undefined reference 错误,因为在链接时发现找不到某个函数的实现文件,本例中 test.o 文件中包含了 test() 函数的实现,所以如果按下面这种方式链接就没事了。

    gcc -o main main.o test.o

    【扩展】:其实上面为了让大家更加清楚底层原因,我把编译链接分开了,下面这样编译也会报 undefined reference 错,其实底层原因与上面是一样的。

    gcc -o main main.c //缺少test()的实现文件

    需要改成如下形式才能成功,将 test() 函数的实现文件一起编译。

    gcc -o main main.c test.c //ok,没问题了

    2. 链接时缺少相关的库文件(.a/.so)
    在此,只举个静态库的例子,假设源码如下。
    在这里插入图片描述
    先把test.c编译成静态库(.a)文件

    gcc -c test.c
    ar -rc test.a test.o

    至此,我们得到了 test.a 文件。我们开始编译 main.c

    gcc -c main.c

    这时,则生成了 main.o 文件,然后我们再通过如下命令进行链接希望得到可执行程序。

    gcc -o main main.o

    你会发现,编译器报错了:

    /tmp/ccCPA13l.o: In function `main’:
    main.c:(.text+0x7): undefined reference to ‘test’
    collect2: ld returned 1 exit status

    其根本原因也是找不到 test() 函数的实现文件,由于该 test() 函数的实现在 test.a 这个静态库中的,故在链接的时候需要在其后加入 test.a 这个库,链接命令修改为如下形式即可。

    gcc -o main main.o ./test.a //注:./ 是给出了test.a的路径

    【扩展】:同样,为了把问题说清楚,上面我们把代码的编译链接分开了,如果希望一次性生成可执行程序,则可以对 main.c 和 test.a 执行如下命令。

    gcc -o main main.c ./test.a //同样,如果不加test.a也会报错

    3. 链接的库文件中又使用了另一个库文件
    这种问题比较隐蔽,也是我最近遇到的与网上大家讨论的不同的问题,举例说明如下,首先,还是看看测试代码。
    在这里插入图片描述
    从上图可以看出,main.c 调用了 test.c 的函数,test.c 中又调用了 fun.c 的函数。
    首先,我们先对 fun.c,test.c,main.c 进行编译,生成 .o 文件。

    gcc -c func.c
    gcc -c test.c
    gcc -c main.c

    然后,将 test.c 和 func.c 各自打包成为静态库文件。

    ar –rc func.a func.o
    ar –rc test.a test.o

    这时,我们准备将 main.o 链接为可执行程序,由于我们的 main.c 中包含了对 test() 的调用,因此,应该在链接时将 test.a 作为我们的库文件,链接命令如下。

    gcc -o main main.o test.a

    这时,编译器仍然会报错,如下:

    test.a(test.o): In function `test’:
    test.c:(.text+0x13): undefined reference to ‘func’
    collect2: ld returned 1 exit status

    就是说,链接的时候,发现我们的 test.a 调用了 func() 函数,找不到对应的实现。由此我们发现,原来我们还需要将 test.a 所引用到的库文件也加进来才能成功链接,因此命令如下。

    gcc -o main main.o test.a func.a

    ok,这样就可以成功得到最终的程序了。同样,如果我们的库或者程序中引用了第三方库(如 pthread.a )则同样在链接的时候需要给出第三方库的路径和库文件,否则就会得到 undefined reference 的错误。

    4 多个库文件链接顺序问题
    这种问题也非常的隐蔽,不仔细研究你可能会感到非常地莫名其妙。我们依然回到第3小节所讨论的问题中,在最后,如果我们把链接的库的顺序换一下,看看会发生什么结果?

    gcc -o main main.o func.a test.a

    我们会得到如下报错.

    test.a(test.o): In function `test’:
    test.c:(.text+0x13): undefined reference to ‘func’
    collect2: ld returned 1 exit status

    因此,我们需要注意,在链接命令中给出所依赖的库时,需要注意库之间的依赖顺序,依赖其他库的库一定要放到被依赖库的前面,这样才能真正避免 undefined reference 的错误,完成编译链接。

    5. 在c++代码中链接c语言的库
    如果你的库文件由c代码生成的,则在 c++ 代码中链接库中的函数时,也会碰到undefined reference 的问题。下面举例说明。

    首先,编写 c 语言版库文件:
    在这里插入图片描述
    编译,打包为静态库:test.a

    gcc -c test.c
    ar -rc test.a test.o

    至此,我们得到了 test.a 文件。下面我们开始编写 c++ 文件 main.cpp
    在这里插入图片描述
    然后编译main.cpp生成可执行程序:

    g++ -o main main.cpp test.a

    会发现报错:

    /tmp/ccJjiCoS.o: In function `main’:
    main.cpp:(.text+0x7): undefined reference to ‘test()’
    collect2: ld returned 1 exit status

    原因就是 main.cpp 为 c++ 代码,调用了 c 语言库的函数,因此链接的时候找不到,解决方法:即在 main.cpp 中,把与 c 语言库 test.a 相关的头文件包含添加一个 extern “C” 的声明即可。例如,修改后的 main.cpp 如下:
    在这里插入图片描述

    g++ -o main main.cpp test.a

    再编译会发现,问题已经成功解决。

    转自《“undefined reference to” 问题解决方法》

  • 相关阅读:
    Sample XPS Documents Download
    触发器中的inserted表和deleted表
    Using freewheel.labs.autodesk.com to auto generate preview images of DWF files on your web site
    解除SQL对组件"Ad Hoc Distributed Queries"的"STATEMENT'OpenRowset OpenDatasource"的访问
    读写xps
    XPS文件,在Windows XP下的打开查看阅读和打印方法。
    Learning to Reference Inserted and Deleted Tables
    Get value from updated, inserted and deleted
    Reinstall Microsoft Helper Viewer
    如何查找文件的IFilter
  • 原文地址:https://www.cnblogs.com/Jimmy104/p/13182968.html
Copyright © 2011-2022 走看看