C++基础-静态库与动态库

举报
码农爱学习 发表于 2021/12/29 23:10:46 2021/12/29
【摘要】 C++基础-静态库与动态库

1 静态链接库(*.lib)

如果在程序中使用静态链接库,那么链接器在链接的过程中会将.obj文件.lib文件组织成可执行exe文件,也就是将.lib中的代码链接到可执行文件中,因此生成的exe文件比较大。 程序运行时,将全部数据加载到内存。如果程序体积较大,功能较为复杂,那么加载到内存中的时间就会比较长,最直接的一个例子就是双击打开一个软件,要很久才能看到界面。这是静态链接库的一个弊端。 但程序在发行时不需要提供库文件。

1.1 静态库优点总结

  1. 代码装载速度快,执行速度略比动态链接库快

  2. 程序在发行时不需要提供库文件,不存在兼容性问题

1.2 静态库缺点总结

  1. 使用静态链接生成的可执行文件体积较大,包含相同的公共代码,造成浪费

  2. 程序可扩展性差

2 动态链接库(*.dll)

动态链接库又分为两种加载方式:隐式加载显式加载

2.1 隐式加载

隐式加载,也称载入时加载,是程序载入内存时加载所需的dll文件,且该dll随主进程始终占用内存。在编码时需要使用#pragma comment(lib,"myDll.lib")获得所需函数的入口。注意该.lib与静态链接库的.lib文件不同,静态链接库的.lib中包含了所需函数的代码,动态链接库的.lib仅指示函数在dll文件中的入口

隐式加载也会有静态链接库的问题,如果程序稍大,加载时间就会过长

2.2 显式加载

显式加载,也称运行时加载,是在程序运行过程中加载,不需要该dll时则将其释放。在需要时使用LoadLibrary加载,不需要时使用FreeLibrary释放。如果在LoadLibrary时该dll已经在内存,则只需将其引用计数加1,如果其引用计数减为0则移出内存。

使用动态链接库的程序在发行时需要提供dll文件。在编译时,如果使用隐式链接则需要提供.lib文件,生成可执行文件后则不再需要该.lib。如果使用显式链接,在编译时不需提供.lib文件。

显式加载将较大的程序分开加载的,程序运行时只需要将主程序载入内存,软件打开速度快,用户体验好。

2.3 动态库优点总结

  1. 更加节省内存并减少页面交换

  2. dll文件与exe文件独立,只要输出接口不变(即名称、参数、返回值类型和调用约定不变),更换dll文件不会对exe文件造成任何影响,因而极大地提高了可维护性和可扩展性

  3. 不同编程语言编写的程序只要按照函数调用约定就可以调用同一个dll函数

  4. 适用于大规模的软件开发,使开发过程独立、耦合度小,便于不同开发者和开发组织之间进行开发和测试

2.4 动态库缺点总结

  1. 使用动态链接库的应用程序不是自完备的,它依赖的dll模块也要存在,如果使用载入时加载(隐式加载),程序启动时发现dll不存在,系统将终止程序并给出错误信息。而使用运行时加载(显式加载),系统不会终止,但由于dll中的导出函数不可用,程序会加载失败

  2. 性能损失

  3. 存在兼容性问题

2.5 动态链接库使用示例

dll源码:

#include <Windows.h>  
#include <stdio.h>  
 
extern "C" {
    _declspec(dllexport) int testAdd(int x, int y)
    {
        return x + y;
    }
}

使用隐式链接:

​
#include"stdafx.h"
using namespace std;
 
#pragma comment(lib,"myDll.lib")//加载动态库
 
extern "C" {
    _declspec(dllimport) int testAdd(int x, int y);
}
int   main(int   argc, TCHAR  *argv[]) {
    _tprintf(_T("sum is %d\n"), testAdd(2,5));
    system("pause");
    return 0;
}

使用显示链接:

#include"stdafx.h"
using namespace std;
 
int   main(int   argc, TCHAR  *argv[]) 
{
    HINSTANCE h = LoadLibrary(_T("myDLL"));//加载动态库
    GetErrorMessage(GetLastError(), 0);
    int(*pAdd)(int, int) = NULL;
    pAdd = (int(__cdecl *)(int, int))(GetProcAddress(h, "testAdd"));
    GetErrorMessage(GetLastError(), 0);
    if (pAdd == NULL) {
        FreeLibrary(h);
        return 0;
    }
    int sum = pAdd(239, 23);
    _tprintf(_T("sum is %d\n"), sum);
    FreeLibrary(h);
    system("pause");
    return 0;
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。