Lex*_*nko 1 c++ dll visual-studio lib
您能帮我了解一下,为什么从dll导入函数和数据时我们需要.lib文件吗?
我听说,它包含来自相应dll的导出函数和数据元素的列表,但是当我使用CFF Explorer探索我的dll时,我发现dll已经具有导出函数的地址,因此从理论上讲我可以链接我的.dll的程序,没有任何其他文件。
您能否详细解释一下.lib文件中存储的数据类型?
而且,是的,我知道,Visual Studio迫使我们将.lib文件添加到其他依赖项部分,但是为什么它真正需要它们呢?
当您的源代码静态调用导出的DLL函数或静态访问导出的DLL变量时,这些引用将作为指针编译到可执行文件的中间目标文件中,并在运行时填充其值。
当链接程序将编译器生成的目标文件组合成最终可执行文件时,它必须弄清楚所有编译器生成的引用实际上是指什么。如果它无法匹配可执行文件中某段代码的给定引用,则需要将其与外部DLL匹配。因此,它需要知道什至要查看哪些DLL,以及这些DLL如何导出内容。DLL可能会按名称或按序号导出给定的函数/变量,因此链接器需要一种方法,将代码引用所使用的标识符映射到EXPORTS特定.dll文件表中的特定条目(尤其是通过序号)。静态链接.lib文件为链接器提供了该映射信息(即,FunctionA映射到123DLL中的Ordinal XYZ.dll,FunctionB映射到_FunctionB@4DLL ABC.dll等中的名称)。
链接器然后可以IMPORTS使用有关EXPORTS所需的适当条目的信息填充可执行文件的表,然后使代码中的DLL引用指向正确的IMPORTS条目(如果链接器无法将编译器生成的引用解析为一段代码,在您的可执行文件(或特定的DLL导出)中,它会中止并显示“无法解析的外部”错误)。
然后,在运行时加载可执行文件时,OS Loader会查看IMPORTS表以了解需要哪些DLL导出,因此它可以将适当的DLL加载到内存中,并IMPORTS使用实际的内存地址更新表中的条目。基于每个DLL的EXPORTS表(如果引用的DLL无法加载,或者找不到引用的导出,则OS Loader将中止加载可执行文件)。这样,当您的代码调用DLL函数或访问DLL变量时,这些访问将转到正确的位置。
如果您的源代码在运行时通过显式调用动态访问DLL函数/变量,则情况将大不相同GetProcAddress()。在那种情况下,.lib这些访问不需要静态链接文件,因为您自己的代码正在处理将DLL加载到内存中并查找要使用的导出文件。
但是,有第三个选项将上述情况混合在一起:您可以编写代码以静态访问DLL函数/变量,但可以使用链接器的延迟加载功能(如果有)。在那种情况下,您仍然需要.lib访问的每个延迟加载DLL的静态链接文件,但链接器会DELAYLOAD在可执行文件中使用对DLL导出的引用填充一个单独的表,而不是填充该IMPORTS表。它将编译器生成的DLL引用指向您的编译器RTL中的存根,该存根将用以下地址替换引用:GetProcAddress()当在运行时首次访问存根时,这样就避免了在加载时由OS Loader填充引用的需求。即使加载时不存在DLL导出,这也可使您的可执行文件正常运行,并且即使从未使用过DLL也可能根本不需要加载DLL(当然,如果您的可执行文件确实尝试访问DLL导出)动态且无法加载,您的代码可能会崩溃,但这是一个单独的问题)。
| 归档时间: |
|
| 查看次数: |
100 次 |
| 最近记录: |