微网站方案,怎么做移动网站吗,美食网站开发与设计文献综述,wordpress支持多域名目录
1、问题说明
2、dll库的隐式加载与动态加载
2.1、dll库的隐式加载
2.2、dll库的显式加载
3、使用Process Explorer查看进程加载的dll库信息以及动态加载的dll库有没有加载成功
3.1、使用Process Explorer查看进程加载的dll库信息
3.2、使用Process Explorer查看动态…目录
1、问题说明
2、dll库的隐式加载与动态加载
2.1、dll库的隐式加载
2.2、dll库的显式加载
3、使用Process Explorer查看进程加载的dll库信息以及动态加载的dll库有没有加载成功
3.1、使用Process Explorer查看进程加载的dll库信息
3.2、使用Process Explorer查看动态启动的库有没有加载成功
4、dll库加载失败原因详细分析与说明
4.1、dll位数与依赖它的模块位数不一致导致dll库加载失败
4.2、dll库依赖的库有问题导致dll加载失败
4.2.1、dll库依赖的库在当前系统中找不到
4.2.2、dll库调用其依赖的库中的接口但该接口在被依赖的库中找不到
4.3、使用Dependency Walker工具查看dll库的依赖关系以及调用的接口
5、最后 最近技术群一个朋友遇到一个程序启动异常以及dll库加载失败的问题找我帮忙看一下看看是什么原因导致的。其实这个问题不难只要之前详细看过我博客相关文章的朋友肯定能很快定位出来的。本文对dll库加载失败导致程序启动报错以及dll库加载失败的常见原因进行总结以供大家参考。
1、问题说明 朋友在用VS调试运行他们的程序时程序中有异常在VS的输出窗口中也看到了相关打印如下所示 然后接下来在使用LoadLibraryEx去加载某个dll库时也加载失败了LoadLibraryEx返回NULL如下所示 可以确定截图中绝对路径中的dll文件是存在的但还是加载失败了。 至于为什么要用LoadLibrary而要用扩展接口LoadLibraryEx并且传入LOAD_WITH_ALTERED_SEARCH_PATH参数可以查看我之前写的文章查看开源操作系统ReactOS源码解决dll库动态库加载失败问题调用LoadLibrary加载失败https://blog.csdn.net/chenlycly/article/details/129200442 我们在项目中遇到过几次使用LoadLibrary加载dll库失败的问题dll库的路径是正确的文件是存在的但就是加载失败当时深入研究了一下参考Reactos开源系统中的regsvr32.exe中加载dll库的源码实现将LoadLibrary改成了LoadLibraryEx并传入LOAD_WITH_ALTERED_SEARCH_PATH参数。 2、dll库的隐式加载与动态加载 程序启动时系统会给程序分配指定大小的进程空间虚拟内存空间系统先将exe主程序依赖的多个dll库加载到进程空间中然后再将exe主程序文件加载到进程空间中然后进入main函数程序开始运行。如果启动过程有dll库加载失败非动态加载且会弹出报错提示框则程序启动终止程序启动失败 程序中引用dll调用dll中的接口在dll加载时可分隐式加载和动态显式加载两种方式。隐式加载是引入dll库对应的lib库在链接时需要链接到代码中调用的dll的导出接口
2.1、dll库的隐式加载 所谓隐式加载就是在程序中使用#pragma预编译指令引入dll库对应的lib导入库 #pragma comment( lib, libcurl.lib) 或者在VS的工程配置中配置导入库 对于隐式加载的库在引入lib导入库之后并包含dll库的头文件就可以直接在代码中调用dll库的API接口了。 隐式加载的dll库在程序启动时就加载了上面已经讲了程序启动时dll库的加载流程如果dll库加载失败则立即终止exe主程序的启动流程程序启动失败。
2.2、dll库的显式加载 dll库的显式加载是调用LoadLibrary或者LoadLibraryEx去动态地加载dll库。 对于显式加载的库需要调用GetProcAddress接口去获取dll库中API接口的函数然后通过该地址去调用API函数。比如如下的一段代码 BOOL AutoRegsvr32( LPCTSTR lpszDllPath )
{if ( lpszDllPath NULL ){return;}// 改用LoadLibraryEx并使用LOAD_WITH_ALTERED_SEARCH_PATH参数避免部分系统无法加载到dll的问题。HINSTANCE hInstLib LoadLibraryEx( lpszDllPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH );if ( NULL hInstLib ){return FALSE;}typedef HRESULT (*DllRegisterServer)(void);DllRegisterServer dllRegisterServer (DllRegisterServer)GetProcAddress( hInstLib, DllRegisterServer );if ( dllRegisterServer ! NULL ){HRESULT hr dllRegisterServer();}else{FreeLibrary(hInstLib);return FALSE;}FreeLibrary(hInstLib);return TRUE;
} 显式加载的dll库不会在程序启动时加载而是在代码执行到LoadLibrary或者LoadLibraryEx函数的调用时才会动态的加载。如果dll库加载失败也不会导致程序启动失败。 当动态加载dll库失败时不像通过dll对应的lib导入库隐式调用dll库不会弹出报错提示框。对于通过dll对应的lib导入库隐式调用dll库加载失败时一般是在程序启动时如果依赖的库在当前系统中找不到则会报出类似如下的错误 如果程序中调用的接口在对应的dll库中找不到一般是库与库之间的版本不一致导致的则会报类似如下的错误 如果是动态加载dll失败不管是哪种原因都不会弹出上述报错提示框。 在这里给大家重点推荐一下我的几个热门畅销专栏欢迎订阅博客主页还有其他专栏可以去查看
专栏1该精品技术专栏的订阅量已达到520多个专栏中包含大量项目实战分析案例有很强的实战参考价值广受好评专栏文章持续更新中预计更新到200篇以上欢迎订阅
C软件调试与异常排查从入门到精通系列文章汇总https://blog.csdn.net/chenlycly/article/details/125529931 本专栏根据多年C软件异常排查的项目实践系统地总结了引发C软件异常的常见原因以及排查C软件异常的常用思路与方法详细讲述了C软件的调试方法与手段以图文并茂的方式给出具体的项目问题实战分析实例很有实战参考价值带领大家逐步掌握C软件调试与异常排查的相关技术适合基础进阶和想做技术提升的相关C开发人员 考察一个开发人员的水平一是看其编码及设计能力二是要看其软件调试能力所以软件调试能力排查软件异常的能力很重要必须重视起来能解决一般人解决不了的问题既能提升个人能力及价值也能体现对团队及公司的贡献 专栏中的文章都是通过项目实战总结出来的包含大量项目问题实战分析案例有很强的实战参考价值专栏文章还在持续更新中预计文章篇数能更新到200篇以上 专栏2本专栏涵盖了C多方面的内容是当前重点打造的专栏订阅量已达160多个专栏文章已经更新到400多篇持续更新中...
C/C实战进阶专栏文章持续更新中...https://blog.csdn.net/chenlycly/category_11931267.html 以多年的开发实战为基础总结并讲解一些的C/C基础与项目实战进阶内容以图文并茂的方式对相关知识点进行详细地展开与阐述专栏涉及了C/C领域多个方面的内容包括C基础及编程要点模版泛型编程、STL容器及算法函数的使用等、数据结构与算法、C11及以上新特性不仅看开源代码会用到日常编码中也会用到部分新特性面试时也会涉及到、常用C开源库的介绍与使用、代码分享调用系统API、使用开源库、常用编程技术动态库、多线程、多进程、数据库及网络编程等、软件UI编程Win32/duilib/QT/MFC、C软件调试技术排查软件异常的手段与方法、分析C软件异常的基础知识、常用软件分析工具使用、实战问题分析案例等、设计模式、网络基础知识与网络问题分析进阶内容等。 专栏3
C常用软件分析工具从入门到精通案例集锦汇总专栏文章持续更新中...https://blog.csdn.net/chenlycly/article/details/131405795 常用的C软件辅助分析工具有SPY、PE工具、Dependency Walker、GDIView、Process Explorer、Process Monitor、API Monitor、Clumsy、Windbg、IDA Pro等本专栏详细介绍如何使用这些工具去巧妙地分析和解决日常工作中遇到的问题很有实战参考价值 专栏4
VC常用功能开发汇总专栏文章持续更新中...https://blog.csdn.net/chenlycly/article/details/124272585 将10多年C开发实践中常用的功能以高质量的代码展现出来。这些常用的高质量规范代码可以直接拿到项目中使用能有效地解决软件开发过程中遇到的问题。 专栏5
C 软件开发从入门到精通专栏文章持续更新中...https://blog.csdn.net/chenlycly/category_12695902.html 根据多年C软件开发实践详细地总结了C/C软件开发相关技术实现细节分享了大量的实战案例很有实战参考价值。 3、使用Process Explorer查看进程加载的dll库信息以及动态加载的dll库有没有加载成功 我们可以使用Process Explorer工具查看程序加载的哪些dll库以及这些dll库的详细信息。还可以查看动态加载的库有没有加载成功。
3.1、使用Process Explorer查看进程加载的dll库信息 可以使用Process Explorer工具查看进程加载的dll库列表在dll列表中可以看到加载的dll库的详细信息。打开Process Explorer后 在进程列表中找到目标进程点击选中该进程下方就会显示本进程加载的dll库列表在dll列表中可以查看这些库的详细信息比如加载的dll库的路径、库的版本等。通过库的路径或版本确定是否加载了正确版本的dll库。 注意如果是在电脑上第一次启动Process Explorer需要在第一次启动该工具时点击工具栏中的“View DLLs”图标按钮 才会显示目标进程加载的库列表。默认情况下显示的是句柄占用信息。 前段时间有粉丝朋友告诉我微软官方最近更新升级了Process Explorer工具微软官方提供的工具软件的主界面发生了变化询问新版本如何查看进程占用的dll列表于是我到微软官网下载了该工具。其实很简单要查看进程加载的dll列表直接点击下方的“DLLs”标签页即可 3.2、使用Process Explorer查看动态启动的库有没有加载成功 上面我们说了隐式加载的dll会在程序启动时加载如果dll库加载失败则程序的启动会被立即终止而动态加载的dll不会在程序启动时加载不会影响程序的启动。所以程序启动起来后只会存在动态加载的dll库加载失败隐式加载的dll库肯定都成功加载起来了否则程序会启动失败。 如何判断动态启动的库有没有加载成功呢其实很简单只要看dll库列表中有没有这个给dll就知道了。 那程序运行时我们怎么感知动态加载的dll库没有加载成功呢只能根据程序业务来判断即执行到动态库相关的业务没有正常执行时则可能时动态加载的dll库加载失败导致的。在我们的项目中底层若干业务模块就是动态加载的上层产品根据自己的需要去选择性加载部分业务模块即可我们在产品开发联调时经常遇到dll库动态加载失败的问题所以我在处理这方面问题时比较有经验一点。
4、dll库加载失败原因详细分析与说明 这里我们讨论一下dll加载失败的原因不管是通过dll库的导入库隐式加载的还是通过调用LoadLibrary或者LoadLibraryEx动态加载的原因都是一样的主要有以下三个原因 1问题dll的位数与依赖它的模块位数不一致 2问题dll依赖的库在当前系统中找不到 3问题dll调用底层库的接口在底层库中找不到。 dll隐式加载失败与dll动态加载失败不同的地方在于现象有所有不同。dll隐式加载失败时一般在程序启动时会弹出报错提示框而dll动态加载失败时则不会弹出报错提示框开发人员只能根据业务异常去感知。至于弹出什么样的报错提示框上面我已经讲过了在此不再赘述。
4.1、dll位数与依赖它的模块位数不一致导致dll库加载失败 如果dll库加载失败我们可以确认一下dll库的位数是否与依赖该dll的模块依赖该dll的模块可能是其他dll也可能是exe主程序的位数一致因为32位dll库是不能和64位模块混用的位数必须要一致才能使用。当然这种情况在项目中比较少见这只是一种可能的原因实际项目中比较少一般不用关注这种情况。比如32位的exe主程序是不能加载使用64位dll库的如果将位数不同的模块混在一起程序启动时回报0xC000007B错误如下所示 什么情况下会出现模块与模块之间的位数不一致呢比如我们在日常开发调试过程中遇到的一个问题发布32位程序时要将相关C运行时库一起打包发布结果错误拷贝了64位运行时库现在大家用的基本都是Win10系统系统中既有32位的库也有64位的库导致程序启动报0xC000007B错误。关于0xC000007B错误的实战分析案例可以查看我之前写的文章 使用Dependency Walker和Process Explorer排查程序启动时缺少ucrtbase.dll等运行时库以及报0xC000007B错误https://blog.csdn.net/chenlycly/article/details/131505299 至于如何查看dll、exe等二进制文件的位数可以用dumpbin.exe或者PE查看工具EXE Explorer相关查看方法可以查看我的文章使用Dumpbin工具查看C二进制文件的位数、时间戳及dll库的依赖关系https://blog.csdn.net/chenlycly/article/details/140153214如何查看exe和dll等二进制文件的生成时间时间戳和位数32位/64位https://blog.csdn.net/chenlycly/article/details/140043291
4.2、dll库依赖的库有问题导致dll加载失败 dll库依赖的库有问题当前问题dll依赖的更下层的库主要有两种情况 1dll库依赖的库在当前系统中找不到 2dll库中调用了其依赖库中的接口但该接口在被依赖的库中找不到。 4.2.1、dll库依赖的库在当前系统中找不到 如果dll库依赖的库在当前系统中找不到则该dll库会加载失败加载dll之前会先将当前dll依赖的库先加载起来依赖的库都加载起来后才会去加载当前的dll。 如果该dll库是隐式加载的则一般在程序启动时加载会报类似这个错误 这个问题在我们项目中也经常出现引发这类问题可能有两个典型的场景 1一个场景是在发布程序时没有将程序模块依赖的C/C运行时dll库一起发布而这些运行时库在其他电脑上可能没有所以我们在发布程序时要将相关运行时库带上。2另一个场景是底层模块因为重构或者业务需要新增了一个dll模块没有通知上层产品导致上层软件产品在打包时没有将新增的dll库打包进去。 4.2.2、dll库调用其依赖的库中的接口但该接口在被依赖的库中找不到 如果dll库调用其依赖的库中的接口在被依赖的库中找不到则该dll库也会加载失败。如果该dll库是隐式加载的则在程序启动时会报类似这个错误 出现这类问题一般是库与库的版本不一致导致的。在编译时引用了正确的dll库的导入库lib编译是没问题的但在程序打包时拷贝的是老版本的dll库导致程序运行时出现调用的接口在底层的库中找不到。 至于为什么在依赖库中找不到接口呢可能找不到的接口在新版本库中被删除了或者接口名称被修改了亦或是接口的参数被修改了比如增加了参数、删除了参数或者修改了参数类型。关于接口参数被修改导致找不到接口的实例 可以查看我之前写的文章 使用Process Explorer和Dependency Walker排查dll动态库没法调试的问题dll库加载失败导致没法动态调试https://blog.csdn.net/chenlycly/article/details/140803687 还有一种情况就是程序中调用了Windows系统的系统dll库中的某个接口该接口只在高版本的Windows系统中才有比如只在Win10系统才有Win7系统中的系统库中没有这个接口这样将程序拷贝到Win7系统中运行就会报接口找不到的错误因为Win7系统库中没有这个接口。
4.3、在某些系统上会出现LoadLibrary加载dll库失败的问题需要使用LoadLibraryEx接口 我们在项目中遇到过几次使用LoadLibrary加载dll库失败的问题dll库的路径是正确的文件是存在的但就是加载失败当时深入研究了一下参考Reactos开源系统中的regsvr32.exe中加载dll库的源码实现将LoadLibrary改成了LoadLibraryEx并传入LOAD_WITH_ALTERED_SEARCH_PATH参数。
4.4、使用Dependency Walker工具查看dll库的依赖关系以及调用的接口 对于上述dll依赖的库问题无论是依赖的库找不到还是调用的接口在下层库中找不到直接使用Dependency Walker工具打开这个问题dll查看即可找到问题。 关于使用Dependency Walker查看库的依赖关系排查问题的项目问题实战分析案例可以查看我之前写的文章使用Process Explorer和Dependency Walker排查C程序中dll库动态加载失败问题https://blog.csdn.net/chenlycly/article/details/140731158使用Dependency Walker和Process Explorer排查瑞芯微工具软件RKPQTool.exe启动报错的问题https://blog.csdn.net/chenlycly/article/details/140731614使用Process Explorer和Dependency Walker排查dll动态库没法调试的问题dll库加载失败导致没法动态调试https://blog.csdn.net/chenlycly/article/details/140803687
5、最后 本文根据多年的项目实战经验对dll库加载失败导致程序启动报错以及dll库加载失败的常见原因进行了总结有一定的实战参考价值。本文的内容不仅对开发新人有用这些内容很多有若干年开发经验的人可能也不太了解他们对系统特性不太了解对这些人可能也很有用。