关于静态库(Static library or Archive library)

来源:互联网 发布:android语音助手源码 编辑:程序博客网 时间:2024/04/29 17:19

静态库就是把原来的目标代码放在一起,连接的时候链接程序根据每一份目标代码的符号表查找相应的符号(函数和变量的名字) 找到就把该函数里面需要定位的符号进行定位,然后将整块函数代码放进可执行文件里,否则报错。
例如:
test.c
extern int global;
void f(void);
int main(void)
{
  f();
  ++global;
  return 0;
}

testa.c
extern void g(void);
int global=0;
void f(void){g();}

testb.c
static int local=1;
void g(void){--local;}

对上面三个文件,可以直接编译链接:$gcc test.c testa.c testb.c
现在做成静态库,首先编译testa.c testb.c:$gcc -c testa.c testb.c
生成testa.o testb.o:$nm *.o        //nm用于查看目标代码文件可执行文件和库文件的符号表数据
testa.o:
00000010 T f
00000004 D global

tesbb.o:
0000000c T g
00000004 d local

上面T表示全局可见的代码,D表示全局可见的数据,d表示局部数据(连接程序在为非本模块的代码查找符号时会忽略它)。
接着创建库libtest.a,把testa.o testb.o放进去:$ar rc libtest.a testa.o testb.o
以后就可以这样来编译test.c了:$gcc test.c -L. -ltest
其中“-L.”指出苦的位置是当前目录(当前目录用“.”表示),而参数“-ltest”告诉连接程序可以在库文件“libtest.a”找到符合要求的代码和数据。
连接过程如下:
首先在main中发现符号f,便在库中查找f,把其对应代码复制到可执行文件中,并给出一个确定的地址,再将这个地址填入调用指令(call f),然后递归的查看f中有没有需要定位的符号……至连接结束。
另外对于call f这个指令,在f的地址没有确定之前,汇编程序仅仅是把f所表示的地址用适当数目的空白字节填上,直到链接程序算出了f的地址,再回过头来把实际的地址填入。

这样,在输出文件中你会发现库中所有的符号(变量或函数)都有了确定的地址。

原创粉丝点击