linux - 从共享库调用函数是如何工作的?
问题描述
当您在运行前加载共享库并将其提供的符号(即函数)添加到全局偏移表中时。
当你调用它提供的函数时会发生什么?因为您已经编译了代码,所以该函数必须已经指向某个地方。
解决方案
假设您有一个hello
包含以下文件的项目:
- 主文件
- 函数.cpp
- 类.cpp
现在你想用g++
. 构建过程将如下所示:
---------------- ------- -------------- -------------
| function.cpp | ---> | g++ | ---> | function.o | | libstdc++ |
---------------- ------- -------------- -------------
\ /
------------ ------- ---------- ------ ---------
| main.cpp | -------> | g++ | ---> | main.o | --> | ld | ---> | hello |
------------ ------- ---------- ------ ---------
/
------------- ------- ----------- /
| class.cpp | ------> | g++ | ---> | class.o | /
------------- ------- -----------
这g++
是将源文件一一编译成目标文件的编译器。它只检查语法错误、未定义的函数或变量。虽然cpp
(C Preprocessor) 在编译器之前执行,但这是另一个话题。在编译完所有源文件后ld
,作为链接器的 . 将您的目标文件链接到一个可执行文件中。现在,假设main.cpp
调用一个名为hello-function
、在 中实现function.cpp
和使用std::cout
、已定义libstdc++
(C++ 标准库)的函数。当代码有效时,编译器编译main.cpp
成目标文件。当所有目标文件通过链接器时,它将读取这些对象并找到引用的函数和变量。如果你不通过function.o
(其中包含hello-function
实现)到链接器,你会得到一个错误说undefined reference
。现在,让我们假设main.cpp
调用外部库中可用的函数。如果您没有为链接器指定库,它将显示undefined reference
. 当没有错误时,链接器将所有目标文件链接到一个可执行文件中,并放置有关生成的可执行文件所依赖的共享库的信息。
在您的程序编译和链接后,您可以执行该程序。当您执行它时,您的操作系统(在本例中为 Linux)将可执行文件加载到内存中。之后,它读取文件并确定它需要哪些库,如果尚未加载,则加载它们。然后它执行程序,当它找到对外部库的引用时,它会将引用转换为实际内存位置并调用它。程序完成执行后,您的操作系统会释放未使用的内存并卸载任何未使用的库。
此外,如果您的程序链接到的共享库的版本与您的程序在链接阶段链接的版本不同,您可能会遇到“分段错误”。
推荐阅读
- java - Spring Boot bean 覆盖
- node.js - 密码重置在环回 3.0 中不起作用
- mysql - MariaDB 默认浮点数不能包含小数位
- java - 将语言区域设置到数组中以在循环中使用
- android - 为什么我们设计UI的Android Studio的编辑区域或主要活动看不到?
- c# - 尝试使用 xsd.exe .NET 实用程序从 C# 类生成 XSD 时出错
- html - 无法以 Angular 5 进行生产构建
- rabbitmq - 如何在 RabbitMQ 中获取 LVC 交换以在 RabbitMQ 执行中持久保存缓存值?
- pandas - 扩展比较数据框的列并返回差异
- java - 如何在java中将通用对象添加到列表中?