《windows核心编程》C/C++运行库的 DLL版本 和 静态版本 的区别?

u0116snail 2014-02-20 11:53:33
今天看《windows核心编程》,有段话:

下面是书上的说明代码:
void ExeFuc()
{
PVOID pv = DllFuc();
free(pv);
}

PVOID DllFuc()
{
return(malloc(100));
}

这是书上原话:
“ 如果EXE 和 DLL 都链接到C/C++运行库的DLL版本,那么代码将会正常工作,如果其中之一或两个模块都链接到C/C++运行库的静态版本,free调用就会失败。”

问题一:
什么叫做 C/C++运行库的DLL版本 ? 什么叫做 C/C++运行库的静态版本?
问题二:
另外,对于书上这段话,该如何理解?
...全文
799 23 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
谁学逆向工程 2016-03-03
  • 打赏
  • 举报
回复
引用 21 楼 qq_27564553 的回复:
提醒一下 lib库有两种, 一种是包含了函数所在DLL文件和文件中函数位置的信息,称为导出库,就是动态lib;简单点说就是相当于一个.h头文件,对dll文件(.c文件)进行声明。 一种是函数索引和实现都在其中,编译后所有代码都嵌入到宿主程序。
Crawl.W 2016-02-17
  • 打赏
  • 举报
回复
引用 15 楼 xiaoyuanyuan2009 的回复:
回答问题一:C++运行库就是C++函数所在的文件,C++函数有两个版本,一个版本在DLL文件里,一个在LIB文件里。DLL版本是动态链接的,也就是在程序运行的时候在去DLL文件里找函数体的代码。LIB是静态链接的,就是在你编译的时候就把函数体的代码复制到你的EXE里
提醒一下 lib库有两种, 一种是包含了函数所在DLL文件和文件中函数位置的信息,称为导出库,就是动态lib;简单点说就是相当于一个.h头文件,对dll文件(.c文件)进行声明。 一种是函数索引和实现都在其中,编译后所有代码都嵌入到宿主程序。
13820 2014-08-01
  • 打赏
  • 举报
回复
引用 2 楼 adlay 的回复:
C/C++运行库的DLL版本 就是 free/malloc 函数的实现在一个单独的 mscrt.dll 里面,所以你的 EXE 和你的 DLL 都是调用的这个 mscrt.dll 中的同一份代码。 C/C++运行库的静态版本 就是把 malloc/free 的实现拷贝到你编译出来的文件里面,所以你的 EXE 和 DLL 调用的是各自的一份函数实现的拷贝。 用静态版本会失败是因为 malloc/free 在申请释放内存的时候需要一个堆的句柄,而这个句柄是作为全局变量来使用的,全局变量的话是每个 dll/exe 都会存在一份的,如果是使用的 mscrt.dll 中的,它们是同一个句柄,没有问题。如果使用的不同的拷贝,则由于句柄不同,Debug 版本会检测出错误来。 Release 版本可能不报错,但是内存可能不会释放成功。
我也有这么个问题,但还是有一点想不通就是,如果那个dll静态链接了c++运行库,exe加载了那个dll,然后再exe中调用那个ExeFuc的函数,哪怕dll和exe都各自有一个堆句柄,那么我exe调用的那个函数也都是exe进程分配与释放自己的堆啊. 所以为什么会有影响呢
u0116snail 2014-04-13
  • 打赏
  • 举报
回复
引用 2 楼 adlay 的回复:
C/C++运行库的DLL版本 就是 free/malloc 函数的实现在一个单独的 mscrt.dll 里面,所以你的 EXE 和你的 DLL 都是调用的这个 mscrt.dll 中的同一份代码。 C/C++运行库的静态版本 就是把 malloc/free 的实现拷贝到你编译出来的文件里面,所以你的 EXE 和 DLL 调用的是各自的一份函数实现的拷贝。 用静态版本会失败是因为 malloc/free 在申请释放内存的时候需要一个堆的句柄,而这个句柄是作为全局变量来使用的,全局变量的话是每个 dll/exe 都会存在一份的,如果是使用的 mscrt.dll 中的,它们是同一个句柄,没有问题。如果使用的不同的拷贝,则由于句柄不同,Debug 版本会检测出错误来。 Release 版本可能不报错,但是内存可能不会释放成功。
学习了
u0116snail 2014-04-13
  • 打赏
  • 举报
回复
引用 10 楼 jianwen0529 的回复:
建议LZ去看下 /MD /MT(VS)的区别,大概就明白了吧! LS几个说的大概思路是对的,就是堆分配的不同方式不同,new/malloc和delete/free只能在同堆里,跨堆会错误!
谢谢
u0116snail 2014-04-13
  • 打赏
  • 举报
回复
引用 16 楼 xiayuanzhong 的回复:
问题一: 什么叫做 C/C++运行库的DLL版本 ? 什么叫做 C/C++运行库的静态版本? 答:malloc可能在msvcr90.dll也可能在msvcr100.dll,甚至msvcr110.dll。这取决于编译器版本。 问题二: 另外,对于书上这段话,该如何理解? 答:VC2008写出来的malloc可能会在90版本的库,VC2012写出来的free可能110版本的库。这两个malloc和free是不能匹配的。
谢谢
mujiok2003 2014-02-21
  • 打赏
  • 举报
回复
引用 7 楼 zhao4zhong1 的回复:
[quote=引用 6 楼 mujiok2003 的回复:] 这里要说的是资源分配的一个原则:谁申请的就有由谁释放。 DllFuc分配了资源,则应提供另一个释放资源的接口。
个人意见:此处的谁指同一个进程中的同一个线程。[/quote] 不完全是。 一个线程分配,在另外的线程释放, 这样例子也很多。
赵4老师 2014-02-21
  • 打赏
  • 举报
回复
跨进程线程申请释放内存可以用GlobalAlloc和GlobalFree
mujiok2003 2014-02-21
  • 打赏
  • 举报
回复
引用 7 楼 zhao4zhong1 的回复:
[quote=引用 6 楼 mujiok2003 的回复:] 这里要说的是资源分配的一个原则:谁申请的就有由谁释放。 DllFuc分配了资源,则应提供另一个释放资源的接口。
个人意见:此处的谁指同一个进程中的同一个线程。[/quote] 是的。
幻夢之葉 2014-02-21
  • 打赏
  • 举报
回复
建议LZ去看下 /MD /MT(VS)的区别,大概就明白了吧! LS几个说的大概思路是对的,就是堆分配的不同方式不同,new/malloc和delete/free只能在同堆里,跨堆会错误!
dahaiI0 2014-02-21
  • 打赏
  • 举报
回复
我的理解是如果exe和DLL静态链接CRT,exe和dll各占一个堆,在exe的堆上new,然后再DLL的堆上delete,势必会崩溃,再者静态链接CRT,各自的new/delete实现都可能未必一样。 动态版的exe和DLL共享一个全局堆,可跨模块new/delete,但做法不规范。所以牢记哪个模块申请的就应该哪个模块释放。
_船长_ 2014-02-21
  • 打赏
  • 举报
回复
主要涉及windows的内存管理方面,进程启动,如果采用DLL连接方式,msvcrt*.dll在进程地址空间只有一份拷贝,然后调用_CRTDLL_INIT(),初始化一个堆栈,这个堆栈由全局的_crtheap标识 而采用静态连接方式,在每个模块都会有一份拷贝,调用_CRTDLL_INIT(),因此每个模块都存在一个堆栈,并由该模块中的_crtheap标识。 静态连接结果: A模块申请的内存由B模块释放,导致失败,因此A模块的内存由A模块中的_crtheap标识,B模块中的_crtheap无法标识,释放失败。
赵4老师 2014-02-21
  • 打赏
  • 举报
回复
引用 6 楼 mujiok2003 的回复:
这里要说的是资源分配的一个原则:谁申请的就有由谁释放。 DllFuc分配了资源,则应提供另一个释放资源的接口。
个人意见:此处的谁指同一个进程中的同一个线程。
MewX 2014-02-21
  • 打赏
  • 举报
回复
问题一: 什么叫做 C/C++运行库的DLL版本 ? 什么叫做 C/C++运行库的静态版本? 答:malloc可能在msvcr90.dll也可能在msvcr100.dll,甚至msvcr110.dll。这取决于编译器版本。 问题二: 另外,对于书上这段话,该如何理解? 答:VC2008写出来的malloc可能会在90版本的库,VC2012写出来的free可能110版本的库。这两个malloc和free是不能匹配的。
谁学逆向工程 2014-02-21
  • 打赏
  • 举报
回复
回答问题一:C++运行库就是C++函数所在的文件,C++函数有两个版本,一个版本在DLL文件里,一个在LIB文件里。DLL版本是动态链接的,也就是在程序运行的时候在去DLL文件里找函数体的代码。LIB是静态链接的,就是在你编译的时候就把函数体的代码复制到你的EXE里
赵4老师 2014-02-21
  • 打赏
  • 举报
回复
引用 13 楼 mujiok2003 的回复:
[quote=引用 7 楼 zhao4zhong1 的回复:] [quote=引用 6 楼 mujiok2003 的回复:] 这里要说的是资源分配的一个原则:谁申请的就有由谁释放。 DllFuc分配了资源,则应提供另一个释放资源的接口。
个人意见:此处的谁指同一个进程中的同一个线程。[/quote] 不完全是。 一个线程分配,在另外的线程释放, 这样例子也很多。 [/quote] 虽然可以跨线程,但此时要加锁。
www_adintr_com 2014-02-20
  • 打赏
  • 举报
回复 1
C/C++运行库的DLL版本 就是 free/malloc 函数的实现在一个单独的 mscrt.dll 里面,所以你的 EXE 和你的 DLL 都是调用的这个 mscrt.dll 中的同一份代码。 C/C++运行库的静态版本 就是把 malloc/free 的实现拷贝到你编译出来的文件里面,所以你的 EXE 和 DLL 调用的是各自的一份函数实现的拷贝。 用静态版本会失败是因为 malloc/free 在申请释放内存的时候需要一个堆的句柄,而这个句柄是作为全局变量来使用的,全局变量的话是每个 dll/exe 都会存在一份的,如果是使用的 mscrt.dll 中的,它们是同一个句柄,没有问题。如果使用的不同的拷贝,则由于句柄不同,Debug 版本会检测出错误来。 Release 版本可能不报错,但是内存可能不会释放成功。
SKATE11 2014-02-20
  • 打赏
  • 举报
回复
是不是静态加载和动态加载dll
mujiok2003 2014-02-20
  • 打赏
  • 举报
回复
这里要说的是资源分配的一个原则:谁申请的就有由谁释放。 DllFuc分配了资源,则应提供另一个释放资源的接口。
mujiok2003 2014-02-20
  • 打赏
  • 举报
回复
C/C++运行库说的CRT(C runtime library),有动态版和静态班可选。
加载更多回复(2)

65,180

社区成员

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

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