凤凰体育下载 静态链接库和动态链接库-C / C ++

日期:2021-02-18 02:09:54 浏览量: 106

通常,在编写程序时,我们必须包含很多头文件,因为我们可以避免重新创建轮子,并且软件构建不能仅由一个人完成。但是您知道引用的头文件中的功能如何执行吗?这将涉及链接库! ! !

有两种库,一种是静态链接库,另一种是动态链接库,无论使用哪种类型的库,要使用它们c++ 动态链接库,您都必须在程序中包含相应的头文件。让我们首先回顾程序编译的过程。如下图所示:

c++ 动态链接库

让我们看一下在每个阶段与gcc命令一起生成的文件:

gcc -c helloWorld.c

生成一个helloWorld.o文件,该文件是从源文件编译的程序集文件。链接之前,该文件不是可执行文件。

gcc -o helloWorld helloWorld.c

生成的是ELF格式(不同于Windows)的helloWorld可执行文件。该文件是链接后的可执行文件。

1。静态链接库

什么是静态链接?即,在链接阶段,将源文件中使用的库函数与程序集生成的目标文件.o组合在一起,以生成可执行文件。可执行文件可能相对较大。

这种链接方法的优点是它便于程序移植,因为可执行程序与库函数无关,并且可以在任何环境中执行。

缺点是:文件太大,以完全静态方式生成的简单打印文件为857K。但是通过动态链接生成的同一可执行文件只需要8. 4K。

文件的内容非常简单,只需一个printf(“ hello world!\ n”);

由于包含了库文件stdio,因此静态编译的文件非常大。如果您想尝试,可以这样编译它:

gcc -static -o print print.c

在Linux中,静态库为lib * .a,动态库为lib * .so。

让我们编写一个库文件,生成一个静态库,然后尝试调用它。

一个简单的添加功能,头文件是

c++ 动态链接库

头文件的源文件:

c++ 动态链接库

让我们在下面生成静态库:

输入:g ++ -c add.cpp生成.o目标文件

然后使用ar命令进一步生成库libadd.a:

ar -crv libadd.a add.o

通过这种方式,将生成静态链接库libadd.a。

让我们在下面写一个测试文件:

#include 
#include "./addlib/add.h"
using namespace std;
int main()
{
    int number1 = 10;
    int number2 = 90;
    cout << "the result is " << add(number1, number2) << endl;
    return 0;
}

因为我的目录结构是add.cpp,addlib(文件夹),在addlib中是头文件和静态库,所以include使用相对路径查找头文件add.h。

让我们编译以下文件:

g++ -o test test.cpp -L./addlib -ladd

-L是指定加载库文件的路径

-l是要加载的指定库文件。

运行它:

可以看出呼叫成功。

2。动态链接库

我们知道,使用静态链接时,文件将非常大,并且实现一个非常小的功能通常会占用大量空间,并且每次升级库文件时,都必须重新编译源文件,即非常不方便。

详细信息如下:

c++ 动态链接库

对于静态编译的程序1和程序2凤凰彩票app ,使用库staticMath。内存中有两个相同的staticMath对象文件,这很浪费空间。一旦程序太多,可能内存不足。

这么多的内存只能运行这几个程序,我真的不甘心。

在这里可以再次使用动态库。让我们看一下动态链接的结果:

c++ 动态链接库

我们看到,在此模型中,两个程序仅使用一个库,并且内存中只有此目标文件的一个副本供所有程序使用。

在程序运行期间动态调用库文件非常方便,并且不占用空间。但是,动态链接的缺点是可移植性太差。如果两台计算机在不同的环境中运行,则动态库的位置将不同。 ,这可能会导致程序失败。

在特定应用中,应合理选择静态和动态! ! !

让我们在下面生成一个动态库:

输入:g ++ -fPIC -shared -o libadd.so add.cpp

通过这种方式,将生成一个动态库libadd.so。

接下来,我们将通过动态链接来编译test.cpp。

输入:g ++ -o test test.cpp -L./addlib -ladd

该命令与刚才的静态链接相同。请注意,-l后跟lib和so之间的库名称。

让我们这样做:

未找到,因为执行程序找不到libadd.so。

c++ 动态链接库

您可以看到未找到测试执行程序使用的libadd.so。 。

原因是在/etc/ld.so.conf文件中设置了动态链接库以查找路径。

您会看到有许多路径设置文件。在ld.so.conf.d中,我们在下面添加libadd.so的路径。

然后再次执行ldconfig命令。

现在您可以成功执行测试文件了。

注意,有人说为什么我的程序中的extern int号;为什么?可以直接编译而无需任何静态链接库,动态链接库。这是因为在链接时已经将由number变量定义的目标文件.o与源文件进行了链接,例如:gcc -o main main.otest.o。如果仅使用main.o进行链接,则无法生成可执行的目标文件。例如,gcc -o main main.c将报告未定义的数字引用。

总而言之,静态和动态链接库的选择取决于情况。通常,建议使用动态链接百家乐下载 ,因为它可以节省内存并促进将来的库文件升级。

g ++(gcc)编译选项

l-shared:指定生成动态链接库。

l-static:指定生成静态链接库。

l-fPIC:表示编译为与位置无关的代码以编译共享库。需要将目标文件创建为与位置无关的代码。这个想法是当可执行程序加载它们时c++ 动态链接库,它们可以放在可执行程序内存中的任何位置。

l-L .:指示要连接的库所在的目录。

l-l:指定链接所需的动态库。搜索动态链接库时,编译器具有隐式命名规则亚博体彩app ,即在给定名称之前添加lib亚博体彩appag捕鱼官网 ,并在其后添加.a / .so以确定库的名称。

l-Wall:生成所有警告消息。

l-ggdb:此选项将为gdb生成尽可能多的调试信息。

l-g:编译器在编译时会生成调试信息。

l-c:仅激活预处理,编译和汇编,即使程序成为目标文件(.o文件)。

l-Wl,options:将参数(选项)传递给链接器ld。如果选项中有逗号,请将选项分成多个选项,然后将其传递给链接器。