前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++基础 静态库与动态库

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

作者头像
xxpcb
发布2020-08-04 16:41:43
1.3K0
发布2020-08-04 16:41:43
举报

静态链接库(*.lib)

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

静态库优点总结

  1. 代码装载速度快,执行速度略比动态链接库快
  2. 程序在发行时不需要提供库文件,不存在兼容性问题

静态库缺点总结

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

动态链接库(*.dll)

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

隐式加载

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

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

显式加载

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

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

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

动态库优点总结

  1. 更加节省内存并减少页面交换
  2. dll文件与exe文件独立,只要输出接口不变(即名称、参数、返回值类型和调用约定不变),更换dll文件不会对exe文件造成任何影响,因而极大地提高了可维护性和可扩展性
  3. 不同编程语言编写的程序只要按照函数调用约定就可以调用同一个dll函数
  4. 适用于大规模的软件开发,使开发过程独立、耦合度小,便于不同开发者和开发组织之间进行开发和测试

动态库缺点总结

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

动态链接库使用示例

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;
}

参考:

https://blog.csdn.net/Hilavergil/article/details/78544424

https://www.nowcoder.com/questionTerminal/8b1ebbb150494810881bd04e190e2cf5?source=relative

http://c.biancheng.net/cpp/html/2754.html

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-05-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码农爱学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 静态链接库(*.lib)
    • 静态库优点总结
      • 静态库缺点总结
      • 动态链接库(*.dll)
        • 隐式加载
          • 显式加载
            • 动态库优点总结
              • 动态库缺点总结
                • 动态链接库使用示例
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档