- 浏览: 2035729 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (651)
- ACE (35)
- BAT (9)
- C/C++ (116)
- fast-cgi (14)
- COM (27)
- python (59)
- CGI (4)
- C# (2)
- VC (84)
- DataBase (29)
- Linux (96)
- P2P (6)
- PHP (15)
- Web (6)
- Memcached (7)
- IME输入法 (11)
- 设计模式 (2)
- 搜索引擎 (1)
- 个人情感 (4)
- 笔试/面试 (3)
- 一亩三分地 (33)
- 历史 (2)
- 地理 (1)
- 人物 (3)
- 经济 (0)
- 不仅仅是笑哦 (43)
- 小故事大道理 (2)
- http://www.bjdsmyysjk120.com/ (0)
- http://www.bjdsmyy120.com/ (0)
- 它山之石可以攻玉 (15)
- 大学生你关注些什么 (28)
- 数据恢复 (1)
最新评论
-
luokaichuang:
这个规范里还是没有让我明白当浏览器上传文件时,STDIN的消息 ...
FastCGI规范 -
effort_fan:
好文章!学习了,谢谢分享!
com技术简介 -
vcell:
有错误os.walk(strPath)返回的已经是全部的文件和 ...
通过python获取目录的大小 -
feifeigd:
feifeigd 写道注意:文章中的CPP示例第二行 #inc ...
ATL入门:利用ATL编写简单的COM组件 -
feifeigd:
注意:文章中的CPP示例第二行 #include " ...
ATL入门:利用ATL编写简单的COM组件
延迟加载DLL
Microsoft Visual C++ 6.0提供了一个出色的新特性,它能够使DLL的操作变得更加容易。这个特性称为延迟加载DLL。延迟加载的DLL是个隐含链接的DLL,它实际上要等到你的代码试图引用DLL中包含的一个符号时才进行加载。延迟加载的DLL在下列情况下是非常有用的:
1)如果你的应用程序使用若干个DLL,那么它的初始化时间就比较长,因为加载程序要将所有需要的DLL映射到进程的地址空间中。解决这个问题的方法之一是在进程运行的时候分开加载各个DLL。延迟加载的DLL能够更容易地完成这样的加载。
2)如果调用代码中的一个新函数,然后试图在老版本的系统上运行你的应用程序,而该系统中没有该函数,那么加载程序就会报告一个错误,并且不允许该应用程序运行。你需要一种方法让你的应用程序运行,然后,如果(在运行时)发现该应用程序在老的系统上运行,那么你将不调用遗漏的函数。例如,一个应用程序在Windows 2000上运行时想
要使用PSAPI函数,而在Windows 98上运行想要使用ToolHelp函数(比如Process32Next)当该应用程序初始化时,它调用GetVersionEx函数来确定主操作系统,并正确地调用相应的其他函数。如果试图在Windows 98上运行该应用程序,就会导致加载程序显示一条错误消息,因为Windows 98上并不存在PSAPI.dll模块。同样,延迟加载的DLL能够使你
非常容易地解决这个问题。
下面让我们从比较容易的操作开始介绍,也就是使延迟加载DLL能够运行。首先,你象平常那样创建一个DLL。也要象平常那样创建一个可执行模块,但是必须修改两个链接程序开关,并且重新链接可执行模块。下面是需要添加的两个链接程序开关:
/Lib:DelayImp.lib
/DelayLoad:Mydll.dll
Lib开关告诉链接程序将一个特殊的函数--delayLoadHelper嵌入你的可执行模块。第二个开关将下列事情告诉链接程序:
1)从可执行模块的输入节中删除MyDll.dll,这样,当进程被初始化时,操作系统的加载程序就不会显式加载DLL。
2)将新的Delay Import(延迟输入)节(称为.didata)嵌入可执行模块,以指明哪些函数正在从MyDll.dll的输入。
3)通过转移到对--delayLoadHelper函数的调用,转换到对延迟加载函数的调用。当应用程序运行时,对延迟加载函数的调用实际上是对--delay LoadHelper函数的调用。该函数引用特殊的Delay Import节,并且知道调用LoadLibrary之后再调用GetProcAddress。一旦获得延迟加载函数的地址, --delayLoadHelper就要安排好对该函数的调用,这样,将来的调用就会直接转向对延迟加载函数的调用。注意,当第一次调用同一个DLL中的其他函数时,必须对它们做好安排。另外,可以多次设定/delayLoad链接程序的开关,为想要延迟加载的每个DLL设定一次开关。
好了,整个操作过程就这么简单。但是还应该考虑另外两个问题。通常情况下,当操作系统的加载程序加载可执行模块时,它将设法加载必要的DLL。如果一个DLL无法加载,那么加载程序就会显示一条错误消息。如果是延迟加载的DLL,那么在进行初始化时将不检查是否存
在DLL。如果调用延迟加载函数时无法找到该DLL,--delayLoadHelper函数就会引发一个软件异常条件。可以使用结构化异常处理(SEH)方法来跟踪该异常条件。如果不跟踪该异常条件,那么你的进程就会终止运行.当--delayLoadHelper确实找到你的DLL,但是要调用的函数不在该DLL中时,将会出现另一个问题。比如,如果加载程序找到一个老的DLL版本,就会发生这种情况。在这种情况下,--delayLoadHelper也会引发一个软件异常条件,对这个软件异常条件的处理方法与上面相
同。下一节介绍的示例应用程序显示了如何正确地编写SEH代码以便处理这些错误。你会发现代码中有许多其他元素,这些元素与SEH和错误处理毫无关系。但是这些元素与你使用延迟加载的DLL时可以使用的辅助特性有关。下面将要介绍这些特性。如果你不使用更多的高级特性,可以删除这些额外的代码。
如你所见, Visual C++ 开发小组定义了两个软件异常条件代码,即VcppException(ERROR_SEVERITY_ERROR,ERROR_MOD_NOT_FOUND)和VcppException(ERROR_SEVERITY_ERROR、ERROR_PROC_NOT_FOUND)。这些代码分别用于指明DLL模块没有找到和函数没有找到。
到现在为止,已经讲述了如何使用延迟加载的DLL和正确解决错误条件的基本方法。但是Microsoft的延迟加载DLL的实现代码超出了迄今为止我已讲述的内容范围。比如,你的应用程序能够卸载延迟加载的DLL。假如你的应用程序需要一个特殊的DLL来打印一个文档,那么这个DLL就非常适合作为一个延迟加载的DLL,因为大部分时间它是不用的。不过,如果用户选择了Print命令,你就可以调用该DLL中的一个函数,然后它就能够自动进行DLL的加载。这确实很好,但是,当文档打印后,用户可能不会立即打印另一个文档,因此可以卸载这个DLL,释放系统的资源。如果用户决定打印另一个文档,那么DLL就可以根据用户的要求再次加载,若要卸载延迟加载的DLL,必须执行两项操作。首先,当创建可执行文件时,必须设定另一个链接程序开关( /delay:unload)。其次,必须修改源代码,并且在你想要卸载DLL时调用--
FunloadDelayLoaded DLL函数:
/delay:unload链接程序开关告诉链接程序将另一个节放入文件中。该节包含了你清除已经调用的函数时需要的信息,这样它们就可以再次调用--delayLoadHelper函数。当调用--
FunloadDelayLoaded DLL时,你将想要卸载的延迟加载的DLL的名字传递给它。该函数进入文件中的未卸载节,并清除DLL的所有函数地址,然后--FunloadDelayLoaded DLL调用FreeLibrary,以便卸载该DLL。
下面要指出一些重要的问题。
首先,千万不要自己调用FreeLibrary,来卸载DLL,否则函数的地址将不会被清除,这样,当下次试图调用DLL中的函数时,就会导致访问违规。
第二,当调用--FunloadDelayLoaded DLL时,传递的DLL名字不应该包含路径,名字中的字母必须与你将DLL名字传递给/DelayLoad链接程序开关时使用的字母大小写相同,否则, --FUnloadDelayLoaded DLL的调用将会失败。
第三,如果永远不打算卸载延迟加载的DLL,那么请不要设
定/delay:unload链接程序开关,并且你的可执行文件的长度应该比较小。
最后,如果你不从用/delay:unload开关创建的模块中调用--FunloadDelayLoaded DLL,那么什么也不会发生, --
FunloadDelayLoaded DLL什么操作也不执行,它将返回FALSE。
延迟加载的DLL具备的另一个特性是,按照默认设置,调用的函数可以与一些内存地址相链接,在这些内存地址上,系统认为函数将位于一个进程的地址中。由于创建可链接的延迟加载的DLL节会使你的可执行文件变得比较大,因此链接程序也支持一个/Delay:nobind开关。因为人们通常都喜欢进行链接,因此大多数应用程序不应该使用这个链接开关。
延迟加载的DLL的最后一个特性是供高级用户使用的,它真正显示了Microsoft的注意力之
所在。当--delayLoadHelper函数执行时,它可以调用你提供的挂钩函数。这些函数将接收--
delayLoadHelper函数的进度通知和错误通知。此外,这些函数可以重载DLL如何加载的方法以及如何获取函数的虚拟内存地址的方法。
发表评论
-
__declspec(novtable) 的用法
2010-11-27 14:37 1589__declspec(novtable) 的用法 __d ... -
解决URLDownloadToFile缓存问题的两种方法
2010-09-09 15:18 2925解决URLDownloadToFile缓存问题的两种方法 ... -
修改richedit背景
2010-07-19 22:52 1652RichEditCtrl::SetBackgroundCo ... -
使用ADO封装类的数据库程序开发实例(下)
2010-07-12 15:30 1480使用ADO封装类的数据库 ... -
使用ADO封装类的数据库程序开发实例(上)
2010-07-12 15:28 1218使用ADO封装类的数据库 ... -
VC防止窗口和控件闪烁的方法
2010-07-09 21:16 20281、将Invalidate()替换为Invalidate ... -
防止窗口闪烁地办法
2010-07-09 21:13 1518防止窗口闪烁地办法 也许我们都碰到过这种情况,当你 ... -
使用ADO _ConnectionPtr
2010-07-06 16:04 5271// GetUser.cpp : Defines the ... -
VC用ADO访问数据库全攻略
2010-07-06 15:29 1801VC用ADO访问数据库全 ... -
深入GetMessage和PeekMessage (引自-MSDN技术组)
2010-06-10 16:59 3731深入GetMessage和PeekMessage (引自 ... -
界面编程总结(1)
2010-06-02 13:32 4016原文地址:http://blog.csdn.net/byx ... -
获取信息的有关Windows API
2010-05-27 10:01 3151获取信息的有关Windows API 1.窗口信息 ... -
VC中如何实现窗口的隐藏
2010-05-13 10:08 7874VC中如何实现窗口的隐藏 用MFC做的Dialog ... -
SetConsoleCtrlHandler 处理控制台消息
2010-05-07 17:32 18160SetConsoleCtrlHandler 处理控制台消 ... -
解决决错误: error C2850: 'PCH header file'
2010-04-27 19:45 1957解决决错误: error C2850: 'PCH hea ... -
VC++ GDI+编程的字体和文本绘制
2010-04-13 13:12 7986字体是文字显示和打印的外观形式,它包括了文字的字样、风格和尺寸 ... -
VC利用GDI+显示透明的PNG图片
2010-04-12 16:59 115521.在你将要使用GDI+的工程中,完成初始化 ... -
GDI+编程基础(一)GDI+ Vs GDI
2010-04-12 15:59 2340下载源代码一、GDI GDI是位于应用程序与不同硬件之间 ... -
VC画图
2010-04-12 15:50 1546BOOL DrawPic(HDC hdc, TCHAR* ... -
对话框的数据交换--MFC深入浅出
2010-04-12 10:43 2467对话框数据交换指以下两种动作,或者是把内存数据写入对应的控 ...
相关推荐
- **编译设置**:在项目编译设置中启用延时加载选项,通常在Visual Studio中可以通过设置"延迟加载DLL"为"是"来实现。 - **链接器选项**:可能需要指定`/DELAYLOAD`链接器选项,后跟要延时加载的DLL名。 - **处理...
除了上述基本方法,还有其他高级技术,如延迟加载DLL(Delay-Loaded DLLs),它允许程序在需要时才加载DLL,进一步优化性能。在Visual Studio中,可以设置项目属性来启用延迟加载。 在使用动态加载DLL时,需要注意...
7. **延迟加载**:为了进一步提高效率,Windows还支持延迟加载DLL。这意味着DLL直到实际调用其函数时才会被加载,这减少了程序启动时的内存占用。 8. **内存管理**:DLL内存加载也涉及到内存管理和内存泄漏的问题。...
本篇文章将深入探讨“动态加载dll”和“动态加载webservice”这两个关键知识点。 **动态加载DLL(Dynamic Link Library)** DLL是一种共享库,它包含可由多个程序同时使用的函数和资源。动态加载DLL意味着在程序...
动态加载DLL的优势在于,它允许程序员延迟加载某些功能,直到它们真正被需要时才执行,这样可以减少应用程序的启动时间和内存占用。 在.NET中,有两种主要的方式来加载DLL文件: 1. 使用`Assembly.Load`方法:此...
例如,在Visual Studio中,可以在项目属性中选择"延迟加载DLL"选项。 2. **加载提示**:当程序需要使用延迟加载的DLL时,系统会查找名为`__delayLoadHelper2`的全局函数,这是系统提供的延迟加载助手函数。它处理了...
DllAddIn动态加载DLL是一种常见的软件开发技术,主要用于在运行时加载和使用动态链接库(Dynamic Link Library,简称DLL)文件。DLL文件是Windows操作系统中的一种共享库,它包含了一组可执行的功能,可供多个应用...
lualib.dll 自测试用的,仅有三个函数:lua_sleep-延时,showm-返回文本,lua_moveto-返回2个数值 太多的东西,没弄明白。 LuaTest.exe 非常简单的LUA执行程序,代替黑窗口_a testlua.lua 不解释了 说明.txt 本文件...
在IT领域,动态加载DLL(Dynamic Link Library)是一种常见的编程技术,主要应用于C++和Windows平台。DLL文件允许开发者将代码库分离出来,使得多个应用程序可以共享同一份代码,节省内存资源并便于更新。本篇将深入...
动态加载DLL与静态加载不同,它允许程序在运行时决定是否以及何时加载DLL,这提供了更大的灵活性。 首先,我们需要了解几个关键的API函数,这些函数是动态加载DLL的基础: 1. `LoadLibrary()`:这个函数用于在运行...
有时候我们不希望出现一运行就加载DLL,而希望在使用到时候...或者我们希望针对相同接口的DLL有选择地加载,那么我们就需要动态加载DLL(延迟载入). 该实例代码演示了动态加载DLL的方法,代码用C++实现,供有需要的朋友参考.
3. **延迟加载**:Windows提供了一种延迟加载DLL的机制,即默认不立即加载DLL,而是在首次调用DLL中的函数时才加载。这样可以减少程序启动时的内存占用和加载时间。 易语言作为一款面向中国用户的编程语言,提供了...
- **调用场景**:当一个进程尝试调用DLL中的函数时,系统开始加载DLL。 - **搜索路径**:系统首先检查调用进程的当前工作目录,然后是系统的系统目录,接着是注册表中指定的路径,最后是动态链接库的搜索路径环境...
这种文件在运行时会先解压缩自身到临时目录,然后执行解压缩后的程序,这样可以隐藏或延迟加载DLL。 6. **代码安全性和隐私保护**:通过这种方式,开发者可以避免源代码或关键功能在安装时被反编译或窃取,因为关键...
7. **延迟加载**:DLL加载器可能支持延迟加载,即只有在实际需要时才加载DLL,这样可以减少启动时的内存占用。 8. **热更新**:在不中断程序运行的情况下,该加载器可能允许更新DLL,这对于持续开发和测试的环境...
在Windows中,DLL加载器主要由系统本身提供的,如NTDLL.DLL、kernel32.dll等,它们负责解析DLL依赖、加载DLL到进程地址空间、初始化DLL函数等。然而,当需要对DLL进行特殊操作或调试时,开发者可能需要使用第三方的...
为了进一步优化性能,Windows提供了延迟加载DLL的功能,即只有在实际调用DLL函数时才加载DLL,而不是在程序启动时立即加载。 9. **DLL注入** DLL注入是一种技术,允许将DLL加载到另一个进程的地址空间中,常用于...
动态链接库(DLL,Dynamic Link...总的来说,动态加载DLL是一种灵活的编程技术,可以用于实现插件系统、延迟加载功能或与其他程序共享代码。理解并掌握DLL动态加载的原理和方法,对于Windows平台的开发者来说至关重要。
延迟加载DLL允许程序在真正需要使用DLL中的函数时才进行加载,而不是在进程启动时立即加载。这种机制在某些情况下特别有用,例如当某些功能模块在程序的生命周期中可能并不需要,或者为了减少启动时间。延迟加载可以...
在项目设置中启用“延迟加载DLL”,然后在需要使用DLL的地方使用`GetProcAddress`。 8. **注意事项** - DLL版本控制:确保调用方和DLL版本兼容,避免因API更改导致的问题。 - 错误处理:在使用DLL时,应处理可能...