ASH*_*HOK 25 c++ linker shared-libraries object-files
shared object(.so
)文件和object(.o
)文件之间的关系是什么?
你可以通过例子解释一下吗?
qua*_*ark 71
假设你有以下C源文件,请调用它 name.c
#include <stdio.h>
#include <stdlib.h>
void print_name(const char * name)
{
printf("My name is %s\n", name);
}
Run Code Online (Sandbox Code Playgroud)
编译时,cc name.c
生成name.o
..o包含name.c中定义的所有函数和变量的已编译代码和数据,以及将其名称与实际代码相关联的索引.如果您查看该索引,请使用该nm
工具(在Linux和许多其他Unix上可用),您会注意到两个条目:
00000000 T print_name
U printf
Run Code Online (Sandbox Code Playgroud)
这意味着:.o中存在两个符号(函数或变量的名称,但不是类,结构或任何类型的名称).首先,标有T
实际包含了定义在name.o
.标U
有的另一个仅仅是一个参考.代码print_name
可以在这里找到,但代码printf
不能.当您的实际程序运行时,它将需要找到所有引用的符号并在其他目标文件中查找它们的定义,以便链接到一个完整的程序或完整的库中.因此,目标文件是在源文件中找到的定义,转换为二进制形式,并且可用于放入完整程序.
您可以逐个链接.o文件,但不要:通常有很多,并且它们是实现细节.你真的更喜欢将它们全部收集到相关对象的包中,并且具有公认的名称.这些包称为库,它们有两种形式:静态和动态.
甲静态库(在UNIX中)几乎总是用后缀.a
(例子包括libc.a
其中是C核心库,libm.a
其是C数学库)等.继续这个例子,您将构建静态库ar rc libname.a name.o
.如果你跑nm
了libname.a
你会看到这个:
name.o:
00000000 T print_name
U printf
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,它主要是一个包含查找其中所有名称的索引的目标文件的大表.就像目标文件一样,它包含每个中定义.o
的符号和它们引用的符号.如果你要链接另一个 .o(例如date.o
to print_date
),你会看到另一个像上面那样的条目.
如果将静态库链接到可执行文件,则会将整个库嵌入到可执行文件中.这就像链接所有单个.o
文件一样.你可以想象这可以使你的程序非常大,特别是如果你使用(因为大多数现代应用程序)很多库.
甲动态或共享库后缀有.so
.它与静态模拟一样,是一个大型的目标文件表,指的是所有编译的代码.你用它构建它cc -shared libname.so name.o
.看一下与nm
静态库有点不同.在我的系统上它包含大约二十二个符号,其中只有两个符号print_name
和printf
:
00001498 a _DYNAMIC
00001574 a _GLOBAL_OFFSET_TABLE_
w _Jv_RegisterClasses
00001488 d __CTOR_END__
00001484 d __CTOR_LIST__
00001490 d __DTOR_END__
0000148c d __DTOR_LIST__
00000480 r __FRAME_END__
00001494 d __JCR_END__
00001494 d __JCR_LIST__
00001590 A __bss_start
w __cxa_finalize@@GLIBC_2.1.3
00000420 t __do_global_ctors_aux
00000360 t __do_global_dtors_aux
00001588 d __dso_handle
w __gmon_start__
000003f7 t __i686.get_pc_thunk.bx
00001590 A _edata
00001594 A _end
00000454 T _fini
000002f8 T _init
00001590 b completed.5843
000003c0 t frame_dummy
0000158c d p.5841
000003fc T print_name
U printf@@GLIBC_2.0
Run Code Online (Sandbox Code Playgroud)
共享库与静态库的区别在于一个非常重要的方式:它不会将自身嵌入到最终的可执行文件中.相反,可执行文件包含对已解析的共享库的引用,而不是在链接时,而是在运行时.这有许多优点:
有一些缺点:
(如果你考虑一下这些是程序使用或不使用引用和指针的原因,而不是直接将类的对象嵌入到其他对象中.这个类比非常直接.)
好的,这是很多细节,我已经跳了很多,比如链接过程实际上是如何工作的.我希望你能遵循它.如果没有要求澄清.
归档时间: |
|
查看次数: |
16629 次 |
最近记录: |