g++链接外部库的过程

源文件到可执行文件的过程分为三个阶段:编译阶段,链接阶段,生成可执行文件阶段

举个例子来理解这三部分,我写了一个main.cpp文件,如下:

#include <iostream>
#include <cmath>  // 包含数学库

int main() {
    double result = sqrt(16.0);  // 使用 libm 库中的 sqrt 函数
    std::cout << "The square root of 16 is " << result << std::endl;
    return 0;
}

1.编译阶段

        在这个阶段,编译器将源代码(main.cpp)编译成目标文件(.o 文件)。编译器会把源代码中的函数调用(sqrt())保留为一个符号引用(symbol reference),但并没有实际的函数代码。也就是说,编译器并不知道 sqrt() 的具体实现,它只是知道程序需要用到一个 sqrt 函数。

2.链接阶段:

        在链接阶段,链接器(Linker)会将所有的目标文件(main.o)以及所需的外部库(libm)结合起来,解决这些符号引用(如 sqrt())。链接器通过查找外部库(比如 libm)中的符号表来找到 sqrt() 函数的实现。

  • 静态链接:如果使用的是静态库(例如 .a 文件),链接器会把 sqrt() 函数的代码从静态库中提取出来,并把这段代码直接嵌入到目标文件(.o 文件)中。这时,main.o 中调用 sqrt() 的地方会被替换成实际的 sqrt() 函数实现代码。

  • 动态链接:如果使用的是动态库(例如 .so.dll 文件),链接器并不把 sqrt() 的代码直接嵌入到目标文件中,而是将一个“地址”或“符号表项”插入到目标文件中。程序在运行时,会通过这个符号表项来动态加载对应的共享库并调用 sqrt() 函数。换句话说,程序运行时,链接器会在运行时去查找和加载对应的动态库,并解析 sqrt() 的具体实现。

3.生成可执行文件:

        如果是 静态链接,最终的可执行文件已经包含了 sqrt() 的实现代码,因此程序不再需要依赖外部的 libm 库文件,它已经将该库的相关部分直接嵌入到了可执行文件中。

        如果是 动态链接,最终的可执行文件仍然只包含对 sqrt() 函数的调用地址(即符号引用),在程序运行时,操作系统会将动态库(如 libm.so)加载到内存,并解析这个符号,从而实现函数的调用。

(个人理解,如有错误,恳请指正)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值