c++动态库加载顺序和同名动态库同时加载问题

C++静态库与动态库:原理、创建、使用与工程实践指南 在软件工程中,库是代码复用和模块化设计的核心概念,它将通用功能封装为可复用的二进制组件。从原理上看,库分为静态库和动态库两种主要形式,其根本差异在于链接时机和代码合并方式。静态库在编译链接期将代码直接复制到最终可执行文件中,生成独立、自包含的程序,但会导致磁盘空间浪费和更新困难;动态库则在运行时被加载和映射到进程内存空间,支持多进程共享同一份代码,显著节省内存并便于模块化更新,但带来了依赖管理和版本兼容性等挑战。这两种技术方案在性能、部署、维护等方面各有优劣,其选择直接影响程序的体积、启动速度、内存占用和部 阅读详情

 本文仅 供学习参考,欢迎提出 宝贵意见

一,同名称动态库加载顺序。  

现有同名称动态库Dllpath.dll 3个,内容非常简单,分别为

extern "C" __declspec(dllexport) void myPrint()
{
OutputDebugStringA("exe path\n");
}


extern "C" __declspec(dllexport) void myPrint()
{
OutputDebugStringA("sys path\n");
}


extern "C" __declspec(dllexport) void myPrint()
{
OutputDebugStringA("SetDllDirectoryA path\n");
}

将这3个dll分别放入exe path(Debug)下,系统目录(我选的是C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin)下,exe path下的新建的目录path下,来检测这3个dll谁会先加载。

main测试代码如下:

void test3()
{
	SetDllDirectoryA("D:\\work\\vs2010_project\\DllPathTest\\Debug\\path"); 
	HINSTANCE dllinstance2 = ::LoadLibrary(L"Dllpath.dll");
	if (dllinstance2)
	{
		typedef void (*PathPrint)();
		PathPrint pp = (PathPrint)GetProcAddress(dllinstance2, "myPrint");
		pp();
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	test3();
	getchar();
	return 0;
}

测试结果为:

打印出exe path。   如果删除exe pah下的该dll,那么打印出SetDllDirectoryA path。 如果再删除Debug\paht下的dll,那么才打印出sys path。

那么由结果可以得出,加载顺序优先级为:exe path > SetDllDirectory path > sys path


2,同名动态库同时加载问题。

在工作中有时候会碰到这样的问题,我一个工程项目需要同时引用多个第三方库(不同厂商SDK),先比如我有工程Demo,要引用两个厂家的sdk,厂家1的sdk内容为

(a.dll, b.dll , c.dll), 厂家2的sdk内容为(a.dll , d.dll, e.dll),注意,这里的两个a.dll 是不一样的,只是名字相同。那么怎么同时加载这两个厂家的sdk呢?

第一种尝试:同时放在exe path下,当然显然不行,覆盖了嘛。

第二种尝试:分别建两个目录,然后把两个厂家的sdk,分别放入两个目录下,然后动态加载(Loadlibrary),当然这里如果两个厂家的sdk太过复杂的话,可以将它们做一次封装。结果为:如果先加载厂家1的sdk,那么再加载厂家2的sdk的时候,加载厂家2的a.dll时候,(Loadlibrary)的返回值为加载厂家1的a.dll相同地址,也就是说,加载厂家2的a.dll是无效的,其实返回的是厂家1的a.dll,那么由此可以得出程序在加载dll的时候,如果加载 到有已经加载过的dll(名字相同),那么就不会重新加载,而是返回之前加载过的dll,(个人猜测,程序是有个dll加载列表的)。

第三种尝试:和第二种尝试几乎 一样,不同之处在于加载两个厂家sdk的时候,不使用动态加载,而是对两个厂家的sdk进行封装(成factory1.dll,  factory2.dll),这两个dll都是使用静态加载的方法去加载各自的 sdk,但是结果和第二种尝试是一样的。

第四种尝试:将两个厂家的sdk封装成com组件,测试结果同样为,先加载的组件有效,后加载的com组件无效。

第五中尝试:根据之前的 尝试,猜测程序是有dll加载列表的,所以只要我有同名的dll,无论怎么加载,后加载的dll都不会成功(返回先加载的dll)(如果有好的方法,请留言,非常感谢)。于是,只能采用进程间通信,(就是开进程加载各自的sdk)这样能解决(但是相对麻烦些了)。


以上为本人的一些测试结果,欢迎提出 不同意见

Linux动态库symbol lookup error:五大原因与系统化排查实战 动态链接是现代软件模块化设计的核心技术,它允许程序在运行时加载共享库,实现代码复用和解耦。其核心原理是运行时链接器(ld-linux.so)根据全局符号表,为程序中的未定义符号查找并绑定到动态库中的定义。这项技术的价值在于提升开发效率、减少内存占用并支持插件化架构,广泛应用于操作系统核心服务、数据库中间件及大型应用程序中。然而,在涉及多个动态库相互调用的复杂系统中,常因**符号可见性**或**ABI兼容性**等问题,引发运行时链接错误。本文聚焦于典型的`symbol lookup error`,深入剖析其五 阅读详情

相关推荐

萤石云C++ SDK接入实践:动态库封装、回调桥接与加载失败排查

在C++工程中引入第三方动态库是常见的集成方式,但动态库的依赖管理、头文件组织与运行期加载问题往往比预想中复杂。理解动态库的加载机制与符号解析原理,是保障程序稳定运行的基础。通过合理的封装层设计、回调线程模型梳理与生命周期管理,可以显著降低集成风险。在实际应用中,视频服务、设备接入等场景常面临库缺失、版本冲突与回调异常等问题。本文以萤石云C++ SDK接入为例,梳理从CMake工程配置、动态库加载到调用封装与问题排查的完整链路,为C++桌面端与服务端集成提供可参考的实践路径。

weixin_30983353的博客 178

链接两个“名字完全一样”的【动态库】,你会怎么处理?

作 者:道哥,10+年嵌入式开发老兵,专注于:C/C++、嵌入式、Linux。 目录 文章目录第一个动态库文件应用程序第二个动态库文件错误做法:直接给它改名正解:patchelf 工具One More Thing 在Linux应用的开发过程中,直接利用现成的第三方库(俗称:轮子)来完成自己的业务功能,是很常见的事情。 不知道你是否遇到这样的场景:应用程序中需要使用两个动态库里的不同功能的函数,但是这两个动态库的作者发生心灵感应了,居然起了完全一样的动态库名字,这该如何是好? 具体来说面对的问题是..

IOT物联网小镇 1988

ATAC-seq数据分析流程学习记录及总结

记录ATAC-seq数据分析流程,主要是参考健明老师的教程以及网上各种学习资源进行总结,网址在下面。

ACGTexplorer的博客 3754

多个c/c++动态库函数同名冲突解决方法

最近某个程序需要调用多个动态库,但是不同的动态库中使用了功能不同的同名函数,导致调用出现偏差,可参考以下解决办法。 样例 假设有动态库libFuncA.so和libFuncB.so,他们的内部实现分别为: /*func_A.c*/ #include<stdio.h> //内部函数 int sayHi() { printf("Hi,this is AAAAA\n"); return 0; } //外部调用函数 int sayOut() { sayHi();

woniuye的博客 7705

告别CMake依赖!在Visual Studio 2022中直接配置VTK 9.4开发环境(附完整项目示例)

本文详细介绍了如何在Visual Studio 2022中直接配置VTK 9.4开发环境,无需依赖CMake。通过图文教程和完整项目示例,帮助C++开发者快速集成VTK库,简化开发流程,提升工作效率。特别适合科学可视化任务的开发者。

weixin_26804345的博客 414

2024年上半年网络工程师下午真题及答案解析

位于MPLS域边缘、连接其他网络的LSR称为( 3 ),区域内部的LSR称为核心LSR(CoreLSR)IP报文进入MPLS网络时,MPLS入口设备分析IP报文的内容并为其添加合适的标签,所有MPLS网络中的LSR根据标签转发数据,当该IP报文离开MPLS网络时,标签由出口LER弹出。LSP的出口LER称为( 6 )。某高校网络拓扑如下图所示,两校区核心(CORE-1、CORE-2),出口防火墙(NGFW-1、NGFW-2)通过校区间光缆互联,配置OSPF实现全校路由收敛,两校区相距40km。

bsefef的博客 2471

dll的加载顺序

总结:dll的加载顺序: (1)EXE所在目录; (2)当前目录GetCurrentDirectory(); (3)系统目录GetSystemDirectory(); (4)WINDOWS目录GetWindowsDirectory(); (5)环境变量 PATH 所包含的目录。 所以使用loadlibrary加载dll使用的路径,但是这个函数会忽略这个路径,只会按既定规则加载dll。所以如果要...

qq_41786318的博客 3064

微型纵向加密在新能源场站中的实战部署与运维避坑指南

本文详细解析了微型纵向加密在新能源场站中的实战部署与运维技巧。通过国密算法SM4实现数据加密,确保新能源场站通信安全,同时提供非侵入式部署方案和运维避坑指南,帮助提升网络稳定性和运维效率。

weixin_30505225的博客 596

C语言 调用的动态库函数重名问题分析

设计两个动态库 第一个动态库:libHelloc: func1.h #ifndef FUNC1_H_ #define FUNC1_H_ int func1(); void func(); #endif func1.c #include "func1.h" int func1() { return 0; } void func() { printf("func at

hknaruto的专栏 7653

工业视觉开发者的福音:用C#玩转VisionMaster算子(非方案版完整教程)

本文为工业视觉开发者提供了一份完整的C#与VisionMaster算子二次开发教程,详细介绍了环境配置、算子调用原理、性能优化技巧及实战案例。通过模板匹配和二维码识别等实例,展示了如何高效集成VisionMaster算子到现有框架中,提升工业自动化视觉检测系统的灵活性和性能。

weixin_29280657的博客 270

NSFC结题报告下载脚本失效?3步教你手动修复下载按钮问题(2024最新版)

针对NSFC官网域名变更导致结题报告下载脚本失效的问题,本文提供了详细的手动修复指南。通过三步操作,教你如何修改用户脚本的域名匹配规则,恢复下载按钮功能,确保NSFC结题报告下载器能继续高效工作。

vscode6remote的博客 751

Windows DLL 的搜索顺序

Dynamic-Link Library Redirection 通常情况下,应用程序加载DLL时的搜索路径顺序如下: The directory from which the application loaded. The system directory. The 16-bit system directory. The Windows directory. The curre...

humadivinity的博客 1173

Euro-NCAP-HWA测试流程中文版V1.1(2023发布)

在本协议中,使用了以下术语:Vehicle undertest (VUT) – 指根据本规程测试的车辆,车上有碰撞前的碰撞缓解或避免系统Global VehicleTarget (GVT) – 指本协议中使用的车辆目标,其定义见TB025—Euro-NCAP全球车辆目标规范v1.0辅助其他车辆(SOV)--指最新的 AEB VRU 测试规程中定义的 "大型障碍车辆"(而非机器人控制的平台),用于本规程中的 "切出 "测试。Time To Collision (TTC) – 指在VUT碰撞GVT之前的剩余时间

小明师兄的博客 595

C/C++多个链接库含有同名函数,编译会报错吗

C/C++多个链接库含有同名函数,编译会报错吗起因基本概念同名函数测试测试1:`.o`目标文件测试2:静态库测试3:动态库同名函数的应用 起因 由于业务需要,我司使用了Mellanox某闭源C++程序,Mellanox推荐的定制化开发方法是:对其链接的动态库进行定制化开发,以添加额外的功能。 在方案讨论阶段,发现很多同事对动态库/静态库所代表的的含义并不十分清楚,特别是当同名函数存在时,编译、链接、运行的结果是什么也没有明确的认识,故写下这篇文章。 基本概念 程序函数库可分为下面几种类型: 静态函数库(

杰特JET的博客 6201

【自然语言处理】情感分析(一):基于 NLTK 的 Naive Bayes 实现

朴素贝叶斯(Naive Bayes)分类器可以用来确定输入文本属于某一组类别的概率。例如,预测评论是正面的还是负面的。它是 “朴素的”,它假设文本中的单词是独立的(但在现实的自然人类语言中,单词的顺序传达了上下文信息)。尽管有这些假设,但朴素贝叶斯在使用少量训练集预测类别时具有很高的准确性。

Data · Model · Agent · Repeat 2173

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

记录一次采坑--如何处理Linux动态库同名函数?

一、背景介绍 需求描述:业务提供一个鉴权的静态库,我只需要从url 和 参数中提取相应的参数传给业务的静态库,将静态库的处理结果直接返回给业务(return < 0, 直接返回403)。 但是最近业务反馈,请求部分url直接返回Error:-1015错误,不符合预期。 二、分析过程 业务刚开始反馈问题,我的第一反应:怎么可能是我的问题,我就仅仅写了一个so(暂时命名1.so),直接调用了你...

lotluck的专栏 2176

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

C/C++语言动态库下的坑

这个问题确实是动态库开发中的一个常见陷阱,尤其是在大型项目中,多个库之间可能会有符号冲突。了解符号解析的规则和采取适当的措施可以帮助避免这些问题。

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 668

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

c/c++依赖静态库、动态库符号问题

一些结论: liba.so / liba.a对应cpp int subfunc(int a, int b) { return a + b; } int funcA(int a, int b) { return subfunc(a, b); } 符号信息 liba.so: func_sub, func_a libB.so / ...

lgfun的专栏 4010

一次使用LD_DEBUG定位问题的经历

在实际工作中,当遇到段错误,我们会很容易的想到这是非法访问了内存导致的,比如访问了已经释放的内存,访问数据越界,尝试写没有写权限的内存等。使用gdb进行调试,查看出异常的调用栈,往往可以定位到问题原因。但是有些时候,段错误问题的定位也没这么简单。本人在工作中就遇到了一个段错误的问题,问题原因不是那么直观,出问题的代码非常简单,直接按照常规的分析方法,很难分析出原因。往内存越界、内存没有权限这个方向分析无法定位问题。可执行文件直接依赖两个动态库,两个动态库有同名符号,这样编译可执行文件的时候无法编译通过。

weixin_38184628的博客 1647

全网首发:由两个库同名函数,看LINUX动态库加载及调用

  最近的字体问题,有点怪: 系统库叫freetype,吾库叫tsfreetype。 执行程序先freetype,随后在使用时加载tsfreetype。功能出错。 使执行程序强制依赖tsfreetype,功能正常。   为什么出错?因为两个库有同名函数。具体来说相当于: freetype库,B函数,调用C。 tsfreetype库,D函数,调用C。   D函数调用C,并不一定调用的是自己库里的,而是看哪个库加载,就先调用哪个。也就是说,LINUX动态库的原则是先入为主。   这个问题怎么解决呢?

柳鲲鹏 1213

Linux——C/C++静态库与动态库完全指南:从制作到实战应用

本文全面介绍了C/C++中静态库和动态库的制作与使用。静态库通过ar工具将.o文件打包为.a文件,编译时嵌入可执行程序;动态库使用-fPIC和-shared生成位置无关的.so文件,运行时加载。文章详细对比了两者在链接时机、内存占用、升级维护等方面的差异,并提供了四种动态库配置方案。还涵盖混合链接优先级、Windows平台差异处理等实用技巧,以及CMake构建示例。开发者可根据项目需求选择合适库类型,提升代码复用性和维护性。

wz_290793的博客 1328

linux动态库相对严谨的做法

当一个项目规模扩大到一定程度,动态库间的冲突容易成为项目的噩梦。 问题在于linux下生成的动态库,默认会导出所有非静态函数、全局变量及静态变量,容易出现不同库中出现同名函数及变量, 而linux下在处理这种同名函数时,仅仅是留下最先加载的函数版本,容易造成莫名奇妙的问题。 windows下的动态库就不容易出现这个问题了,因为只有显式标记的函数和变量才会被导出。 linux下的动态库要达到

tanggula的专栏 732

程序的链接和加载基础(2)

1.7 符号查找路径   通常在.h文件中声明函数,在.c/.cc文件(静态库/动态库)中定义函数。上面的演示中,在需要函数声明的地方,都是手工声明的。   头文件的查找路径,如果#include "header",那么header在当前路径查找,如果#include ,那么header在/usr/include 和 /usr/local/include 路径查找。

zqt520的专栏 808

Hook技术

linux上基于C和C++的hook尝试

jinking01的专栏 4418

动态加载DLL实现不同DLL的相同导出函数调用问题

假设这样的情景:         一个exe加载了两个dll(dll1和dll2,并使用隐式加载)。dll和dll2都同时向外导出一个函数:         int add(int a, int b);         如果在exe中调用了add函数,那么它调用的会是哪个dll的add函数呢?         为了验证这个结果,写了一个测试的例子。两个dll(win32的d

Nicole的成长 3705
上一篇: 安装ubuntu已将该虚拟机配置 为使用64位客户机操作系统错误
下一篇: android MediaCodec的自己碰到的问题
mincheat
博客等级 码龄17年 46粉丝 43原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值