2010-07-01 48 views
7

这是我在本网站的第二篇文章,旨在了解使用gcc编译/链接过程。当我尝试创建可执行文件时,需要在链接时解析符号,但是当我尝试创建共享库时,符号在链接时不会解析。当我尝试使用这个共享库制作可执行文件时,它们可能会被解决。动手:为什么共享库的符号在链接时没有解决?

bash$ cat printhello.c 
#include <stdio.h> 
//#include "look.h" 

void PrintHello() 
{ 
look(); 
printf("Hello World\n"); 
} 

bash$ cat printbye.c 
#include <stdio.h> 
//#include "look.h" 

void PrintBye() 
{ 
look(); 
printf("Bye bye\n"); 
} 

bash$ cat look.h 
void look(); 

bash$ cat look.c 
#include <stdio.h> 

void look() 
{ 
printf("Looking\n"); 
} 

bash$ gcc printhello.c printbye.c 
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crt1.o: In function `_start': 
(.text+0x18): undefined reference to `main' 
/tmp/cck21S0u.o: In function `PrintHello': 
printhello.c:(.text+0x7): undefined reference to `look' 
/tmp/ccNWbCnd.o: In function `PrintBye': 
printbye.c:(.text+0x7): undefined reference to `look' 
collect2: ld returned 1 exit status 

bash$ gcc -Wall -shared -o libgreet printhello.c printbye.c 
printhello.c: In function 'PrintHello': 
printhello.c:6: warning: implicit declaration of function 'look' 
printbye.c: In function 'PrintBye': 
printbye.c:5: warning: implicit declaration of function 'look' 

所以我的问题是为什么当我链接共享库时符号未解决。当我使用这个库来创建一个可执行文件时,需要完成这项工作(解析下游的符号),但这意味着我们需要知道这个库在使用这个库时依赖于什么,但这不是不可取的吗?

谢谢, Jagrati

回答

6

添加-z defs当建立图书馆做你想要的?如果没有,请检查ld手册页,处理未定义符号的选项有很多。

0

链接的没有办法知道,在ELF,其中所述符号是至少(即,其中库)。另一方面,在OS X中,您需要按照您所描述的方式链接库。最后,这是一个设计问题。一个更灵活,另一个更严格。

+0

为什么这会降低投票率?请注意,在OSX上,您可以使用'-flat_namespace'选项使其像其他操作系统一样运行。 Linux操作系统。 – Troubadour 2010-07-01 16:19:55

0

即使构建共享库,它也必须解决所有的依赖关系。

因此,当编译时加载共享库时,它知道在运行时加载哪些其他共享库,以便它可以解决其他依赖关系。

1)建立一个共享(外观。< sharedLib>)库与外观()
2)建立一个共享(HG。< sharedLib>)用针对外表你好()再见()链接库。 < sharedLib>
3)用main()构建应用程序,该应用程序与hg链接。 < sharedlib>

在运行时,应用程序将加载hg。 < sharedlib>这将实习生加载共享库的外观。 < sharedlib>

2

我认为链接选项-Bsymbolic是你在找什么。

+0

本身不够。我在这里有一个-Bsymbolic共享库,用于在运行时访问barfs。 – Kaz 2016-11-23 23:25:33

0

可执行文件需要entry point。但是可以在没有入口点的情况下构建共享库,然后可以使用此共享库编译可执行文件。

3

您似乎并不了解您在第一个命令中要求编译器驱动程序(gcc)执行的操作。由于您没有提供-c(仅编译)选项,因此您要求gcc编译这两个源文件并将它们与标准库(libc)和c运行时启动(通常为crt0)进行链接以生成运行程序。 crt0试图通过调用main()来进入你的程序,这是链接器找不到的未定义符号。它找不到它,因为你的任何一个.c文件中都没有main(),对吧?

因此,关于您的实际问题,“为什么共享库的符号在链接时没有解决?”答案是,“链接时间”是什么意思?通过定义,一个动态链接的程序在启动之前不会“链接”(或者甚至可能还没有,这取决于您的系统。)

在Linux系统上,您可以看到程序依赖于ldd命令(Mac OS使用'otool -L')所依赖的动态库。 ldd的输出会告诉你程序依赖哪些动态库,哪些在库搜索路径中找到,哪些不能找到(如果有的话)。

当动态程序启动时,链接到它的动态链接器定位并加载程序依赖的动态库,并“修复”对外部符号的引用。如果其中任何一个失败,您的程序将无法启动。一个所有以前未解决的符号已经解决,动态链接器返回并且C运行库将调用您的main()函数。 (在Mac OS上它有些不同,但效果相似,链接发生在您的程序启动后。)