mingw64下动态库和静态库链接的真正区别和用法(详细)

这篇具有很好参考价值的文章主要介绍了mingw64下动态库和静态库链接的真正区别和用法(详细)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

笔者一直以来都对mingw64下动态库和静态库链接的真正区别和用法存疑,于是做了一些测试,这篇文章记录了测试过程和测试结果,如果只想知道结果可以跳转到文章末尾

一、准备工作

首先准备三个测试文件
mingw64下动态库和静态库链接的真正区别和用法(详细)
其中add.c最终会被编译会静态库或动态库,被测试文件main.c调用
使用如下命令构建静态库

gcc -c add.c -o add.o
ar rcs libadd.a add.o

得到静态库如下:
mingw64下动态库和静态库链接的真正区别和用法(详细)
接着使用如下命令构建动态库

gcc -fPIC -shared add.c -o libadd.dll

得到动态库如下:
mingw64下动态库和静态库链接的真正区别和用法(详细)

二、测试过程

1.当一个静态库和一个动态库重名,并且位于同一文件夹下,编译器优先链接哪一个

首先把五个文件放在同一路径下
mingw64下动态库和静态库链接的真正区别和用法(详细)
已知在编译指令中,链接libadd.a 和链接libadd.dll都只需要加上以下参数

-ladd

也即这里静态库和动态库可以看做是重名的,于是我们先来测试当输入-ladd的时候,gcc会默认链接哪个库
输入指令:

gcc main.c -I ./ -L ./ -ladd -o normal_two_implicit

得到文件
mingw64下动态库和静态库链接的真正区别和用法(详细)
文件名是为了对比实验方便而设置的,其中normal意味着正常状态,与后面要进行的反常测试相对应,two表示静态库和动态库同时位于同一文件夹下,与之后将某个库移走单独测试剩下的库相对应,implicit意为在链接命令中隐式指出库名称(即-l格式的指明方法),与之后显示给出库的全称的测试对应。
虽然现在得到了可执行文件,但是现在我们还无法判断默认链接的是哪一个库,于是继续进行测试
先把libadd.dll暂时移到其他文件夹里,只保留libadd.a,再键入同样的命令:

gcc main.c -I ./ -L ./ -ladd -o normal_a_implicit

得到文件
mingw64下动态库和静态库链接的真正区别和用法(详细)
这里的exe一定链接的是静态库,而且和上一个exe大小完全相同,因此合理推测前一个exe也是链接了静态库,也即:当两种同名库同时存在于同一文件夹,并且使用-l格式参数隐式指出链接库名称时,gcc优先链接后缀为.a的库(为什么不说优先链接静态库?后续的测试会说明)
然后把libadd.a暂时移到其他文件夹里,只保留libadd.dll,再键入同样的命令:

gcc main.c -I ./ -L ./ -ladd -o normal_dll_implicit

得到文件
mingw64下动态库和静态库链接的真正区别和用法(详细)
文件大小只有54KB,小于前两个,因此这是个链接了动态库的exe

因此得到结论:当一个静态库和一个动态库重名,并且位于同一文件夹下,编译器优先链接后缀.a的库

2.-static参数有什么用

之前一直以为,加了-static就是静态链接,做出来的exe一定就是那种完全可以移植的,但是经过测试以后我发现我大错特错
首先把libadd.a和libadd.dll放回原位
mingw64下动态库和静态库链接的真正区别和用法(详细)
然后输入以下命令:

gcc -static main.c -I ./ -L ./ -ladd -o normal_two_implicit_static

得到:
mingw64下动态库和静态库链接的真正区别和用法(详细)
文件大小为64KB,这说明不出所料地,编译器优先链接了静态库,这和-static关键字很搭,接下来把libadd.dll暂时移走,只留下libadd.a,输入以下命令

gcc -static main.c -I ./ -L ./ -ladd -o normal_a_implicit_static

得到
mingw64下动态库和静态库链接的真正区别和用法(详细)
64KB,链接了静态库,依然在意料之中
这次移走libadd.a,只留下libadd.dll,然后输入以下命令

gcc -static main.c -I ./ -L ./ -ladd -o normal_dll_implicit_static

错误出现了:
mingw64下动态库和静态库链接的真正区别和用法(详细)
错误信息为并没有找到库文件!这和我们的预设也一致,因为-static禁用了动态库,所以不再能找得到动态库dll
测试至此本可以结束,但是这里仍然存在一个疑问:我们到目前为止还没有通过显式的指出文件名来链接库,因为其结果似乎不用想都可以知道,那就是给出什么文件名就链接哪个文件,不可能出现重名的情况,这当然是对的,但是在-static关键字的加持下,似乎在另一个角度出现了有意思的现象
再一次把文件归位在一起
mingw64下动态库和静态库链接的真正区别和用法(详细)
键入如下命令:

gcc -static main.c -I ./ -L ./ libadd.a -o normal_a_explicit_static

得到文件
mingw64下动态库和静态库链接的真正区别和用法(详细)
没有问题
然后键入如下命令

gcc -static main.c -I ./ -L ./ libadd.dll -o normal_dll_explicit_static

根据之前的经验,我猜测:由于-static禁用了动态库链接的选项,那么这条命令应该也会失败并报错,但是奇怪的事情发生了,命令正常运行并且得到了正常的动态库链接exe(因为它的大小为54KB)
mingw64下动态库和静态库链接的真正区别和用法(详细)
至此我们得到了第二个十分有用的结论:-static并不禁用动态链接,它只是禁用了采用隐式指明库名法(即以-l格式指明库名)时动态链接的选项,如果你愿意的话完全可以在有-static的情况下输入完整的动态库dll的全称来进行动态链接

3.编译器靠什么识别一个库时静态库还是动态库(后缀还是二进制内容)

这个疑问乍看起来有些多次一举:后缀为.a的就是静态库,后缀为.dll的就是动态库呀。
但是事实真的如此吗?我们完全可以通过修改后缀名而保持它们的二进制数据并不变化,修改以后真正的静态库后缀为.dll,而真正的动态库后缀为.a,。在这种情况下如果将.a链接进去,编译器会辨别出它实际上是个披着静态库外皮的动态库呢,还是会傻傻地将其当做静态库打包进exe?于是有了下面的测试:
修改后缀名的过程略去
mingw64下动态库和静态库链接的真正区别和用法(详细)
经过修改后缀名,现在这里的.a才是真正的动态库,而.dll才是真正的静态库
键入以下命令:

gcc main.c -I ./ -L ./ -ladd -o unnormal_two_implicit

得到文件
mingw64下动态库和静态库链接的真正区别和用法(详细)
文件只有54KB,这说明它实际上链接了动态库,也即现在的.a库,这与我们测试1中的结论也相同,即:当同名库同时存在时,隐式指明库名会默认优先链接.a库(这也是为什么前面不说优先链接静态库的原因,因为.a不一定是静态库,在本例中它是一个披着静态库后缀的动态库)
于是得到有用的第三条结论:编译器靠二进制内容识别静态库和动态库,而不会被其后缀名所迷惑

三、结论

1.当一个静态库和一个动态库重名,并且位于同一文件夹下,编译器优先链接后缀.a的库
2.-static并不禁用动态链接,它只是禁用了采用隐式指明库名法(即以-l格式指明库名)时动态链接的选项,如果你愿意的话完全可以在有-static的情况下输入完整的动态库dll的全称来进行动态链接
3.编译器靠二进制内容识别静态库和动态库,而不会被其后缀名所迷惑

下面以编程人员的角度,根据以上三条结论再导出出几条实用结论:

Q:当需要把一个dll链接进程序的时候该怎么做?
A:在不确定是否有重名库的情况下,建议直接在编译参数中显式给出库名的全称,如果确定没有重名静态库的话,可以考虑使用-l的参数指出dll的名称

Q:当需要进行静态编译,即把所有库打包放进exe以保证其良好的不受环境依赖性的时候该怎么做?
A:只加一条-static并不会完事大吉,建议仔细检查给出的库中不包含动态库,然后加上-static参数作为最终检查

Q:我要开发一个程序,程序运行时需要调用一些第三方动态库如opencvworld455.dll,但是我又希望我编译出的exe可以单独发布出去让其他人运行,可以做到把opencvworld455.dll静态链接到exe中吗?
A:不能这么做,动态库无法静态链接,这是库的二进制内容差异决定的,要发布依赖第三方dll的可执行文件exe,必须同时打包发布其依赖的第三方dll(有些商业软件为了保证在一些连基本dll环境如msvcr.dll都没有的机器上运行,甚至会将全部dll和exe一起打包发布)

四、注

1.本文省略了一些与主题相关性不高的测试过程,比如测试第一个问题,重名问题时,并没有给出显式指明库名的结果,以及第三个问题,编译器靠什么识别一个库时静态库还是动态库问题中,也没有给出加上-static之后的测试结果,另外仅凭文件大小就判断链接了静态库和动态库未免有些草率,这些问题都从某种程度上显得测试的逻辑性不够严密。但实际上笔者几乎做了一切可以想到的测试,并且通过移走dll再运行exe发现不能运行才判断其为动态链接产物,发现能运行才判断其为静态链接产物,这些测试结果由于结果显而易见和篇幅限制(懒)的缘故在文章中没有给出,感兴趣的读者可以自己试试
2.本文测试的平台为mingw64+windows10,结论并不一定适用于其他平台
3.如有错误,欢迎指正文章来源地址https://www.toymoban.com/news/detail-448582.html

到了这里,关于mingw64下动态库和静态库链接的真正区别和用法(详细)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Linux操作命令&静态库和动态库区别&大小端&孤儿僵尸进程

    cd:切换当前目录 ls:查看当前文件与目录 grep:通常与管道符命令一起使用,用于对一些命令的输出进行筛选和加工 cp:复制文件或文件夹 mv:移动文件或文件夹 rm:删除文件或文件夹 ps:查看进程情况 kill:向进程发送信号 tar:对文件进行打包 cat:查看文件内容 top:查看

    2024年02月16日
    浏览(42)
  • 详解Linux下静态库/动态库的生成和使用(含代码示例和操作流程)&&动态库和静态库的区别

    关于gcc的使用方法可以参考下方链接博客: Linux下详解gcc编译过程(含代码示例) gcc使用教程 库是一种组件技术。 库里封装了数据和函数,提供给用户程序调用。 库只执行到第三阶段编译,没有链接。 库的使用可以使程序模块化,提高程序的编译速度,实现代码复用。

    2024年02月15日
    浏览(45)
  • 动态库和静态库

    1. 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。 2. 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。 3. 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个

    2024年02月09日
    浏览(31)
  • 制作静态库和动态库

    目录 制作静态库 ar命令 使用makefile制作静态库 如何发布自己的静态库给别人呢? 如何使用静态库呢? 方法一 方法二 制作动态库 使用动态库遇到的问题 上面的问题如何解决呢?(如何使用动态库) 1.方法一 2.方法二 3.方法三 4.方法四 搜索优先级 Linux默认头文件的搜索顺序

    2024年02月03日
    浏览(35)
  • 【软件教程】MingW-W64-builds不同版本之间的区别

    https://github.com/niXman/mingw-builds-binaries/releases i686和x86_64的区别 i686和x86_64分别是32位和64位的CPU指令集。i686是x86家族线的一部分,而x86_64也被称为amd64。在处理大型数据库等需要在同一进程中使用大量内存的工作负载时,64位版本将更好地扩展内存。 posix和win32的区别 POSIX是一种

    2024年02月12日
    浏览(53)
  • 【Linux】动态库和静态库

    软链接 命令: ln -s 源文件名 目标文件名 软链接是独立连接文件的,他有自己的inode number,有自己的inode属性和内容。 软链接内部存放的是自己所指向文件的路径。 现实中,我们软链接的应用有,例如电脑桌面的快捷模式等。 inode number 不相同 硬链接 命令: ln 源文件目标文件

    2024年02月11日
    浏览(43)
  • Linux之静态库和动态库

    目录 一、前言 二、对于库的理解 三、静态库 四、动态库 五、动静态库的加载 在之前,我们讲了静态库和动态库,详情请跳转:静态库和动态库 下面我们将从工程师的角度,去了解静态库和动态库的形成过程,以及实现它们的制作。并且了解如何将自己的库交给别人,让别

    2024年01月20日
    浏览(36)
  • [静态库和动态库][VS2022]

    我们写代码,可以分模块去写,最后可以协作,能整合起来; 可以吧代码的实现和声明分离。 比如:我的这篇博客C语言猜拳小游戏就用到了模块化编程 什么是库: 库是写好的现有的,成熟的,可以复用的代码。现实中每个程序都要依赖很多基础的底层库本质上来说库是一

    2024年02月15日
    浏览(36)
  • 动态库和静态库的使用

    库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。就是将源代码转化为二进制格式的源代码,相当于进行了加密,别人可以使用库,但是看不到库中的内容。 常见的库类型 共享库 静态库 动态库 win32平台下,静态库通常后缀为.lib,动态库为.dll 。 linux平台下

    2024年02月03日
    浏览(88)
  • C语言 静态库和动态库生成

    使用ar命令 ar命令用于创建和管理静态库。下面是使用ar命令生成静态库的步骤: ./main: error while loading shared libraries: libcalc.so: cannot open shared object file: No such file or directory 执行直接报错了,说明系统没有找到库位置 而动态库的搜索路径搜索的先后顺序是: 1.编译目标代码时指

    2024年02月08日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包