最近一次偶然的机会,发现了C语言静态库之间一个依赖问题,事情是这样的……
主程序调用静态库A中的一个函数如‘test1()’,静态库A中的这个函数‘test1()’调用了另一个静态库B里面的一个没有入参的函数‘test2()’。后来静态库B里面的函数‘test2()’增加了入参,但是静态库A没有一起重新编译生成,但是使用了这两个静态库的主程序重新编译执行都没有问题。
经过一系列分析,总结下来原因应该是这样的:
1、主程序在链接两个库的时候,静态库A的函数‘test1()’调用的函数‘test2()’在静态库B中可以找得到,因为C语言不支持函数重载,所以带参数和不带参数的函数符号在库里面是一样,所以可以链接成功。
2、主程序执行过程中,当执行到函数‘test2()’的时候,函数入参直接是从相应的寄存器中读取的,所以尽管调用函数‘test2()’的时候没有传参,但函数从寄存器中可以读取到默认值,仍能够正确执行。
//静态库A
#include "slib1.h"
#include "slib2.h"
void test1() {
test2();
//test2(33);
}
//静态库B
#include "slib2.h"
void test2() {
//void test2(int x) {
}
编译生成静态库后,静态库A中显示函数‘test2’未定义:
静态库B的函数‘test2()’加了入参,重新编译生成后,从汇编可以看出,函数的参数是从寄存器获取的:
下面两个截图,则分别是静态库A调用函数‘test2()’不传参和传参的汇编,可以看出来两者的差别就是传参调用多了一步,把参数放入寄存器中。
不传参调用函数
传参调用函数
综上,静态库调用的外部函数也并不是把全部代码都直接放到库里面的,所以如果静态库之间存在依赖关系的话,在写Makefile的时候,一定要当心、处理好这些依赖关系~~