GCC: 加载静态链接库

327 阅读1分钟

我是使用 macos 系统操作的,请先阅读 GCC系列: Homebrew安装GCC和binutils 这篇文章。如果你已经安装了 GCC 编译器,可以继续往下看。

GCC 加载链接库会依赖加载顺序,这样会导致无法调用预期的方法。

下面举例说明。

Car 和 Bus 都有 drive 函数,在 main 里面调用谁的 drive, 取决于链接库的加载顺序。

Car.c 示例代码,如下:

#include<stdio.h>  
#include<stdlib.h> 
 
int drive()
{
    printf("Car driving...\n");
 
    return 0;
}
 
void stop()
{
    printf("Car stop.\n");
}

Bus.c 示例代码,如下:

#include<stdio.h>  
#include<stdlib.h> 
 
int drive()
{
    printf("Bus driving...\n");
 
    return 0;
}
 
void start()
{
    printf("Bus start.\n");
}

这里注意: Car 和 Bus 都有 drive 函数。

现在把 Car.c 和 Bus.c 分别编译生成独立的两个静态库(.so)文件,命令如下:

gcc-4.9 -shared -o libBus.so Bus.c 

gcc-4.9 -shared -o libCar.so Car.c

编译完成之后,会有对应的 so 库文件生成。

接下来,开始使用这两个库文件。

main.c 示例代码,如下:

#include<stdio.h>  
#include<stdlib.h> 
 
//
// 在 gcc 编译器下, 必须声明方法
// 在 clang 编译下, 只是给了警告
//
 
int drive();
void start();
void stop();
 
int main()
{
    drive();
    stop();
    start();
 
    return 0;
}

编译 main.c,如下:

gcc-4.9 -o app main.c -L ./ -lCar -lBus

运行可执行文件 app,如下:

./app 
 
Car driving...
Car stop.
Bus start.

我们交换一下链接库顺序再来编译 main.c,如下重新编译:

gcc-4.9 -o app2 main.c -L ./ -lBus -lCar

再次运行可执行文件 app2,如下:

./app2 

Bus driving...
Car stop.
Bus start.

从执行结果中可以看出,编译时链接库顺序不一样,调用的函数(drive)也不一样。