首页 > 解决方案 > 从共享库调用函数是如何工作的?

问题描述

当您在运行前加载共享库并将其提供的符号(即函数)添加到全局偏移表中时。

当你调用它提供的函数时会发生什么?因为您已经编译了代码,所以该函数必须已经指向某个地方。

标签: linuxcc++shared-librarieslinker

解决方案


假设您有一个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)将可执行文件加载到内存中。之后,它读取文件并确定它需要哪些库,如果尚未加载,则加载它们。然后它执行程序,当它找到对外部库的引用时,它会将引用转换为实际内存位置并调用它。程序完成执行后,您的操作系统会释放未使用的内存并卸载任何未使用的库。

此外,如果您的程序链接到的共享库的版本与您的程序在链接阶段链接的版本不同,您可能会遇到“分段错误”。


推荐阅读