链接器问题 - 未定义的引用

时间:2008-09-27 12:18:49

标签: gcc linker

我的编译器有问题告诉我有一个'未定义的引用'我要在库中使用的函数。让我分享一下这个问题的一些信息:

  • 我正在使用gcc与C进行交叉编译。
  • 我正在调用一个库函数,该函数可以通过包含头文件来访问,该头文件包含另一个包含原型的头文件。
  • 我使用-I包含了headers目录,我确信它已被找到。
  • 我首先创建.o文件,然后在单独的命令中链接它们。

所以我的想法是它可能是我包含库文件的顺序,但我不确定订购它们的正确方法是什么。我尝试在.o文件之前和之后都包含headers文件夹。

有些建议会很棒,也许会解释链接器如何做到这一点。

谢谢!


对答案的回应

  • 库中没有.a库文件,只有.h和.c,所以-l不合适
  • 我对库文件的理解是它只是一个头文件和源文件的集合,但也许它是从源创建的.o文件的集合?!
  • 没有创建库对象文件,也许应该有?是的,似乎我不明白包含和库之间的区别...我将继续努力: - )

感谢所有回复!我学到很多关于图书馆的知识。我想把所有答案都作为公认的答案: - )

6 个答案:

答案 0 :(得分:5)

听起来你没有编译库中的.c文件来生成.o文件。链接器将在通过编译库

生成的.o文件中查找原型的实现

您的构建过程是否编译库.c文件?

如果它实际上只是源代码,为什么称它为“库”?

答案 1 :(得分:4)

标题提供函数声明和函数定义。要允许链接器找到函数的实现(并删除未定义的引用),您需要让编译器驱动程序(gcc)使用-l标志链接函数所在的特定库。例如,-lm将链接数学库。函数的手册页通常指定必须指定哪个库来查找函数。

如果链接器找不到指定的库,则可以使用-L开关添加库搜索路径(例如,-L / usr / local / lib)。您还可以通过LIBRARY_PATH环境变量永久影响库路径。

以下是一些可帮助您调试问题的其他详细信息。按照惯例,库文件的名称以lib为前缀,(以静态形式)具有.a扩展名。因此,系统默认数学库(与-lm链接的那个)的静态链接版本通常位于/usr/lib/libm.a中。要查看给定库定义的符号,可以在库文件上运行nm --defined-only。在我的系统上,在libm.a上运行命令会给出如下输出。

e_atan2.o:
00000000 T atan2

e_asinf.o:
00000000 T asinf

e_asin.o:
00000000 T asin

要查看编译器使用的库路径以及默认情况下加载的库,可以使用-v选项调用gcc。再次在我的系统上,这给出了以下输出。

GNU assembler version 2.15 [FreeBSD] 2004-05-23 (i386-obrien-freebsd) 
using BFD version 2.15 [FreeBSD] 2004-05-23
/usr/bin/ld -V -dynamic-linker /libexec/ld-elf.so.1 /usr/lib/crt1.o 
/usr/lib/crti.o /usr/lib/crtbegin.o -L/usr/lib /var/tmp//ccIxJczl.o -lgcc -lc 
-lgcc /usr/lib/crtend.o /usr/lib/crtn.o

答案 2 :(得分:1)

我担心你混合了库和标题概念。 假设您有一个库libmylib.a,其中包含函数myfunc()以及定义其原型的相应标题mylib.h。在源文件myapp.c中,您可以直接包含标头,也可以包含包含标头的另一个标头。例如:

/* myapp.h
** Here I will include and define my stuff
*/
...
#include "mylib.h"
...

您的源文件如下:

/* myapp.c
** Here is my real code
*/
...
#include "myapp.h"
...
/* Here I can use the function */
myfunc(3,"XYZ");

现在您可以编译它以获取myapp.o

gcc -c -I../mylib/includes myapp.c

请注意,-I只告诉gcc头文件的位置,它们与库本身无关!

现在,您可以将应用程序与真实库链接:

gcc -o myapp -L../mylib/libs myapp.o -lmylib

请注意,-L开关告诉gcc库所在的位置,-l告诉它将代码链接到库。

如果您不执行此操作,则可能会遇到所描述的问题。

可能还有其他更复杂的案例,但是从你的问题来看,我希望这足以解决你的问题。

答案 3 :(得分:1)

发布您的makefile,以及您尝试调用的库函数。即使是简单的gcc makefile也常常有这样的一行:

LIBFLAGS =-lc -lpthread -lrt -lstdc++ -lShared -L../shared

在这种情况下,它意味着链接标准C库,等等

答案 4 :(得分:0)

我猜你必须添加链接器可以找到libraray的路径。在gcc / ld中,您可以使用-L和libraray使用-l。

执行此操作
  

-Ldir, - library-path = dir

     

在标准之前搜索目录dir   搜索目录(此选项必须   在搜索的-l选项之前   那个目录)。

     

-larch, - library = archive

     

在档案中包含档案文件arch   要链接的文件列表。


  

对答案的回答 - 库中没有.a库文件,只有.h和.c,所以-l不合适

那你可能要先创建图书馆吗?

gcc -c mylib.c -o mylib.o
ar  rcs libmylib.a      mylib.o

答案 5 :(得分:0)

使用新版本的gcc构建程序时遇到此问题。通过使用-std = gnu89选项调用gcc来解决此问题。显然这是由于内联函数声明。我在https://gcc.gnu.org/gcc-5/porting_to.html

找到了这个解决方案