动态链接库的链接和运行

news/2024/11/19 16:36:21/

        本文对动态链接库的链接和运行进行一个总结,为什么要分开说呢?因为链接通过生成可执行文件并不代表运行时能找到依赖的动态库。这与静态库是不一样的,因为静态库在编译完成后会库会编译到可执行程序中,但是动态链接库则不然,仅仅只是在可执行文件中打了一个标记,标识依赖哪个动态库文件。如何编译动态库或者如何编译静态库,这个很简单,在创建工程的时候进行就可以了,本文重点讲述动态库编译完成后如何链接到可执行程序中。下面将区分window平台和linux平台进行介绍。

        在编译阶段,如何保证编译可执行程序依赖动态链接库编译通过呢?需要在编译选项中添加-L选项指定依赖动态链接库的路径。

        这里要建立一个认识:如果一个可执行程序依赖另一个动态链接库,那么可执行程序能够正确的编译链接出来,并不代表该可执行之程序可以正常运行,因为在编译链接阶段能够成功仅仅代表可知形程序中依赖的动态链接库中的符号能够在动态链接库中找到,更直白一点的理解就是将可执行程序中的依赖的动态链接库的符号对应的位置打上动态链接库的标签,告知程序依赖哪个动态链接库。那为什么可执行程序可能不会正常运行呢?因为可执行程序仅仅在程序中标记了依赖哪个动态链接库,但是并未标明该动态链接库在哪里,所以运行的时候有可能找不到依赖的动态链接库,这就是可能运行出错的原因。解决问题的方法大致有两种

  • 在编译阶段通过添加编译选项指定动态链接库的位置,例如-Wl -rpath
  • 可执行程序搜索动态链接的路径会有几种默认的顺序,在任意一种方法中加入依赖的动态库均可。例如Linux系统下添加依赖库可以选择LD_LIBRARY_PATH环境变量来完成。

Windows VS Studio 2017

通过vs studio编译的动态库为dll后缀,在vs studio去哪里搜索依赖的动态库呢?下面给出几个路径:

  •  应用程序所在目录,即exe后缀的文件所在路径
  • 系统环境变量path,但是设置系统环境变量会影响所有的工程,还可能会造成符号冲突。
  • 设置工程环境变量,该环境变量仅应用于本工程,影响范围,是比较好的方法。设置方法如下图所示:

上面的总结是运行情况下的总结,那么编译过程中如果依赖dll文件,如何保证编译通过呢?

这个问题在gcc编译器下不存在问题,但是是用使用vs studio则不容易理解,因为生成一个dll会生成三个文件,test.lib test.dll test.h,为了编译通过需要在附近库目录中包含test.lib,在头文件中包含test.h应该就可以编过了。 

补充:

使用vs studio 2017测试,下面将测试过程列出:

  • 创建一个dll工程,需要注意的是一定在要在希望在别的工程调用的函数前面使用_declspec(export) ,只有使用这个符号才可以生成对应的dll和lib文件;如果不使用这个符号,那么将只会生成dll文件(这种情况下,动态链接库文件将无法被隐式加载,只能显式的调用加载dll接口加载),所以我们如果隐式的声明代码的话,一定要使用_declsepc(export)修饰。另外就是这个修饰符_declspec(export)只能放在源文件中修饰函数定义,用这个符号去修饰头文件中的函数声明是没有效果的。创建完成后输出对应的lib文件和dll文件。
//add.h
int add(int a,int b);
//add.cpp
_declspec(export) int add(int a, int b) 
{return a+b;
}
  • 创建一个win32控制台应用程序,在工程目录中创建一个目录,将上一个目录中生成中lib文加入到该目录,将依赖的头文件加入到工程中,通过属性->链接器->常规->附加库目录,添加lib文件所在目录。然后再次属性->链接器->常规->附加依赖项 添加依赖的lib名称(注意包含后缀),再次编译通过。
  • 直接运行第二步的程序,程序报错,提示缺少dll。如下所示:

 总结:上述测试说明了在window下依赖动态链接库的情况下的编译过程与dll无关,仅与lib和头文件有关

但是运行时需要将dll文件放到指定路径中才可以,因为实际运行时是实际加载对应的符号的,如果找不到该dll文件,则无法将生效

Linux gcc

 在gcc编译器编译过程中依赖的动态链接库文件,路径可以通过-L -l 设置依赖的动态库。

在运行过程中so搜索路径也有好几种:

  • 程序编译时用户指定的-Wl -rpath指定的搜索路径
  • 环境变量LD_LIBRARY_PATH指定的路径
  • /etc/ld.so.conf或/etc/ld.so.conf.d指定的路径
  • /lib路径或者/usr/lib路径

参考链接:动态库.lib与.dll关系、visual studio工程库路径配置浅析_动态库为什么会有lib和dll_Coding-Prince的博客-CSDN博客

vs 设置dll依赖库引用路径_vs2019设置dll路径_沐大人的博客-CSDN博客


http://www.ppmy.cn/news/50993.html

相关文章

OSCP-Fish(GlassFish、SynaMan、查看卸载软件、TotalAV提权)

目录 扫描 扫描 nmap 192.168.213.168 -sS -sV -p- -PnPORT STATE SERVICE VERSION 3389/tcp open ms-wbt-server? 3700/tcp open giop CORBA naming service 4848/tcp open http Sun GlassFish Open Source Edition 4…

网络作业7【计算机网络】

网络作业7【计算机网络】 前言推荐网络作业7一. 单选题(共11题,33分)二. 多选题(共2题,10分)三. 填空题(共4题,30分)四. 阅读理解(共1题,27分&…

进程通信(同一主机)

1.概述 进程通信机制包括: 传统的UNIX进程间通信:无名管道、有名管道、信号 System V 进程间通信:消息队列、信号量、共享内存 2.管道通信 2.1无名管道 1.特点 (1)适用具有亲缘关系的进程 (2&#x…

微信小程序php+vue 校园租房指南房屋租赁系统

本着诚信的原则,平台必须要掌握出租方必要的真实可信的信息,这样就可以防止欺诈事件的发生,事后也可以联系找到出租方。并且租金等各方面规范标准化,在这易租房诚信可信的平台让承租方与出租方充分有效对接,既方便了承…

JavaScript字符串操作

ASCII(as key) 字符集(了解) 我们都知道,计算机只能存储 0101010 这样的二进制数字,那么我们的 a ~ z / A ~ Z / $ / /… 之类的内容也有由二进制数字组成的 我们可以简单的理解为, a ~ z / …

Linux服务器出现503 服务不可用错误怎么办?

​  HTTP 503 服务不可用错误代码表示网站暂时不可用。无论您是网站访问者还是管理员,503 页面都很麻烦。尽管该错误表明存在服务器端问题,但对于访问者和网络管理员来说,有一些可能的解决方案。本文将解释Linux服务器出现503 服务不可用错…

微服务下网关聚合Swagger文档、starter统一配置Swagger

一、starter实现统一配置微服务文档 把Swagger配置中的公共部分抽取出来Swagger与SpringBoot整合中,可能会由于版本问题出现各种问题 1、制作starter 参考: 【SpringBoot】自定义启动器 Starter【保姆级教程】用starter实现Oauth2中资源服务的统一配置用…

GenericJackson2JsonRedisSerializer

GenericJackson2JsonRedisSerializer 对于这个不存在的属性, 需要标注为忽略, 否则, 反序列化时, 会报错。 主要也是因为,我们拿不到GenericJackson2JsonRedisSerializer中的mapper,不然,是可以修改mapper的反序列化特性的,把map…