动态库加载相关的问题

清钟沁桐 2013-02-18 09:15:42
#include <stdio.h>
#include <time.h>
#include <windows.h>

int foo (void)
{
printf("foo\n");

// MessageBox(NULL, "foo", "Notice", MB_OK);

return 0;
}

int main(int argc, char* argv[])
{
HINSTANCE hUser32 = LoadLibrary("User32.dll");
DWORD dwMessageBox = (DWORD)GetProcAddress(hUser32, "MessageBoxA");
printf("dwMessageBox GetProcAddress:%0p\n", dwMessageBox);

printf("MessageBox GetProcAddress:%0p\n", MessageBox);

while (1)
{
Sleep(1000);
foo ();
}

return 0;
}


类似如上的一个可执行程序,虽然显示的使用 LoadLibrary 加载了动态库 "User32.dll",但是程序本身并没有使用该动态库中的任何函数,请问程序的运行时会真正加载该动态库?
...全文
423 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
清钟沁桐 2013-02-25
  • 打赏
  • 举报
回复
我需要确定的答案,而非猜测
Kevin1993year 2013-02-25
  • 打赏
  • 举报
回复
从理论上都可以猜测的东西。。。
清钟沁桐 2013-02-24
  • 打赏
  • 举报
回复
Process Explorer 果然是好东西,可以看到即使未使用的dll在显示LoadLibrary之后确实被加载
赵4老师 2013-02-21
  • 打赏
  • 举报
回复
http://technet.microsoft.com/zh-cn/sysinternals/bb896653 适用于 Windows 的 Process Explorer 10.21 版 作者:Mark Russinovich 发布日期: 2006年11月01日 简介您是否曾经想要了解某个程序打开了哪个特定文件或目录?现在您可以找到答案了。 Process Explorer 可显示有关进程已打开或加载哪些句柄和 DLL 的信息。 Process Explorer 的显示由两个子窗口组成。顶部窗口总是显示当前活动进程的列表(包括拥有它们的帐户的名称),而底部窗口中显示的信息取决于 Process Explorer 所处的模式:如果它处于句柄模式下,则可以看到顶部窗口中的所选进程打开的句柄;如果 Process Explorer 处于 DLL 模式下,则可以看到相应进程已经加载的 DLL 和内存映射文件。Process Explorer 还具有强大的搜索功能,可以快速显示哪些进程打开了哪些特定句柄或加载了哪些特定 DLL。 Process Explorer 的独特功能使其可用于跟踪 DLL 版本问题或句柄泄漏问题,还可以让用户深入了解 Windows 和应用程序的工作方式。 Process Explorer 可以在 Windows 9x/Me、Windows NT 4.0、Windows 2000、Windows XP、Server 2003、64 位版本的 Windows(用于 x64 和 IA64 处理器)和 Windows Vista 上运行。
清钟沁桐 2013-02-20
  • 打赏
  • 举报
回复
被映射加载 的 DLL文件 重命名 必然不能成功,于是即可判定?
东莞某某某 2013-02-20
  • 打赏
  • 举报
回复
证明途径:试着重命名DLL文件(注意其他进程是否会加载);使用VS中的查看模块菜单;使用API; 用第三方工具。。。
翅膀又硬了 2013-02-20
  • 打赏
  • 举报
回复
引用 12 楼 zhongyunde 的回复:
被映射加载 的 DLL文件 重命名 必然不能成功,于是即可判定?
重命名必然会成功,不论该动态库是否正在被使用。 被使用中的动态库,exe都可以被重命名,但是不能被删除
东莞某某某 2013-02-20
  • 打赏
  • 举报
回复
引用 13 楼 yunchao630 的回复:
引用 12 楼 zhongyunde 的回复:被映射加载 的 DLL文件 重命名 必然不能成功,于是即可判定?重命名必然会成功,不论该动态库是否正在被使用。 被使用中的动态库,exe都可以被重命名,但是不能被删除
是啊 呵呵 我弄错啦。。不好意思
Kevin1993year 2013-02-19
  • 打赏
  • 举报
回复
引用 9 楼 zhongyunde 的回复:
引用 7 楼 Kevin1993year 的回复:引用 2 楼 zhongyunde 的回复:引用 1 楼 turingo 的回复:当然会加载它。 怎么证明?试想一下,假设你的程序用LoadLibrary加载某个库后并没有使用它,那么编译器可能会优化,所以那一句加载实际上是不存在的;但现在问题是:编译器如何知道你是否用到了该动态链接库呢?假设你的语句中有if语句,判……
这个我个人是这么想的:前面我已经说了,编译器不会优化掉LoadLibrary这个函数,所以当执行该函数时实际上是想操作系统发送一个信号,即我这个程序需要加载该动态连接库,而程序使用动态链接库里面的函数自然是加载并映射地址之后才能使用该动态链接库的,操作系统就算是判断程序没有用该动态链接库也是加载及映射地址后的事情,因此我认为操作系统一定会加载并映射地址。(而且我也不认为加载后操作系统会判断程序是否用该动态链接库,LoadLibrary函数就像是像操作系统申请资源一样,申请的资源未必有机会用到,这个我的解释就是那个if-else的解释)
清钟沁桐 2013-02-19
  • 打赏
  • 举报
回复
引用 7 楼 Kevin1993year 的回复:
引用 2 楼 zhongyunde 的回复:引用 1 楼 turingo 的回复:当然会加载它。 怎么证明?试想一下,假设你的程序用LoadLibrary加载某个库后并没有使用它,那么编译器可能会优化,所以那一句加载实际上是不存在的;但现在问题是:编译器如何知道你是否用到了该动态链接库呢?假设你的语句中有if语句,判断成功则调用动态链接库中的函数,失败则不调用,并且……
楼上说的极是,确实编译器是不敢冒险优化掉!但是操作系统是可以做到,只有在必要的时候才进行加载的!
赵4老师 2013-02-19
  • 打赏
  • 举报
回复
计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构…… 对学习编程者的忠告: 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步对应汇编一行!
Kevin1993year 2013-02-18
  • 打赏
  • 举报
回复
引用 2 楼 zhongyunde 的回复:
引用 1 楼 turingo 的回复:当然会加载它。 怎么证明?
试想一下,假设你的程序用LoadLibrary加载某个库后并没有使用它,那么编译器可能会优化,所以那一句加载实际上是不存在的;但现在问题是:编译器如何知道你是否用到了该动态链接库呢?假设你的语句中有if语句,判断成功则调用动态链接库中的函数,失败则不调用,并且这个判断是由你在运行程序过程中输入值判断的,编译器是无法判断你是否会调用的,这也是为什么编译器没有在有一个new就必须有一个delete与之配对的这样的报错;因此我认为调用了LoadLibrary后只要是该库存在且尚未被加载,系统就一定会加载它,不知道你是否认可我的猜测。
清钟沁桐 2013-02-18
  • 打赏
  • 举报
回复
参见http://blog.chinaunix.net/uid-20476365-id-1942491.html 这种通过dll提供的.h和.lib文件进行链接dll的使用方式,称为隐式链接。用vc开发程序时,几乎所有的系统API调用都用了隐式链接。 .显式链接 在exe创建时不引用.lib文件中的符号,当然也不必包含.h头文件,而是由程序调用LoadLibrary(Ex)以及GetProcAddress函数来获取每个需要使用的函数地址,从而进行dll中的函数调用,这种dll使用方法称为显式链接。显式链接时不生成对应dll的IAT. 由于MessageBox是隐式链接连接中动态库的地址,而dwMessageBox是显式链接中动态库的地址,他们指向同一个动态库,因此两者的地址一致。
清钟沁桐 2013-02-18
  • 打赏
  • 举报
回复
printf("dwMessageBox GetProcAddress:%0p\n", dwMessageBox);
 
    printf("MessageBox GetProcAddress:%0p\n", MessageBox);
2个疑问 1) 以上2个地址 dwMessageBox 和 MessageBox 是一致的,也就是window API中的MessageBox 怎么和User32.dll 库中的MessageBox一致呢? 2) 即使不用 HINSTANCE hUser32 = LoadLibrary("User32.dll"); 加载动态库,仍旧可以使用printf("MessageBox GetProcAddress:%0p\n", MessageBox);简单的得到 该函数指针?
zslInSz 2013-02-18
  • 打赏
  • 举报
回复
LoadLibrary这个已经实现动态加载了。dll已经被映射到进程内存空间了。你都已经可以获得指向函数的指针了。
图灵狗 2013-02-18
  • 打赏
  • 举报
回复
你可以看看dwMessageBox的值。
引用 2 楼 zhongyunde 的回复:
引用 1 楼 turingo 的回复:当然会加载它。 怎么证明?
清钟沁桐 2013-02-18
  • 打赏
  • 举报
回复
引用 1 楼 turingo 的回复:
当然会加载它。
怎么证明?
图灵狗 2013-02-18
  • 打赏
  • 举报
回复
当然会加载它。

64,644

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧