C 运行时静态链接与动态链接中的内存分配
我的程序的架构涉及插件(dll)和exe(显然)。我们是唯一的插件提供商。有人告诉我,如果我们静态链接 c 运行时,在插件中分配内存然后在 exe 代码中释放它是一个潜在的问题。但是,如果我们动态链接它,则只有一个堆,而 c 运行时可以访问所有堆。我们根据这个建议切换到动态链接,但是我们从切换中看到的只是与新运行时的分发和安装相关的令人头痛和麻烦。 (不知道我们在内存分配问题方面避免什么。)
内存分配的影响是什么?假设一个插件分配内存,而 exe 释放它。静态链接 c 运行时与动态链接 c 运行时之间是否有不同的行为?如果我们使用插件,静态链接 c 运行时会遇到麻烦吗?如果我们切换回静态链接,是否会扰乱内存泄漏检测和故障转储报告?
符合 Which VC++ 上的评论提出的一些问题我选择运行时版本 - 静态还是动态? 特别是 我选择哪个 VC++ 运行时版本 - 静态或动态?
在 http://msdn.microsoft.com/en-us /library/abx4dbyh(v=VS.100).aspx。
My program's architecture involves plugins (dlls) and the exe (obviously). We are the only plugin provider. I was told that allocating memory in a plugin and then freeing it in the exe code was a potential problem if we statically linked the c runtime. However, if we dynamically linked it, there was just one heap and the c runtime had access to all of it. We switched to dynamic linking on the basis of this advice, but all we've seen from the switch is headaches and trouble related to distribution and installation of the new runtimes. (Don't know what we avoided in terms of memory allocation problems.)
What are the memory allocation implications? Say a plugin allocates memory and the exe frees it. Is there different behavior between the static vs dynamically linked c runtime? Will we have trouble statically linking the c runtime if we use plugins? If we switch back to static linking, will that mess up the memory leak detection and crash dump reporting?
Is in line with some questions raised by comments on Which VC++ runtime version do I choose - static or dynamic? specifically Which VC++ runtime version do I choose - static or dynamic?
There is also some discussion at http://msdn.microsoft.com/en-us/library/abx4dbyh(v=VS.100).aspx.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您想在一个模块中从堆中分配,并在另一个模块中释放,那么您只需动态链接运行时即可。此外,各方必须动态链接相同运行时。一旦你这样做了,就不会有任何问题了。
现在,这对您的插件来说是一个相当严格的限制,您在执行此操作之前应该三思而后行。强迫所有插件作者与您同步升级是一种沉重的负担。我建议您考虑重构您的接口,以便分配始终与单个模块中的释放配对。这解除了我上面描述的限制,并使您的插件作者的生活更轻松。
至于为什么你仍然遭受运行时错误的困扰,这很难说。我的猜测是,并非所有模块都链接到同一版本的运行时。
在评论中您声明您控制所有插件。这意味着我上面讨论的约束不是强加的,因为您可以轻松地为所有模块使用相同的编译器版本。但是,跨模块堆访问的动态链接规则仍然存在。您必须对同一单一版本的运行时使用动态链接。
If you want to allocate from the heap in one module, and free in another then you simply have to dynamically link the runtime. What's more, all parties must dynamically link the same runtime. Once you do that then there will be no problems.
Now, this is quite a severe constraint to impose on your plugins and you should think twice before doing it. Forcing all plugin authors to upgrade in lock-step with you is a heavy imposition. I would recommend that you consider refactoring your interface so that allocations are always paired with deallocations within a single module. This lifts the constraints I describe above and makes life easier for your plugin authors.
As for why you are still suffering from runtime errors, that's hard to tell. My guess is that not all modules are linking against the same version of the runtime.
In the comments you state that you control all plugins. That means the constraints I discuss above are not an imposition since it is easy for you to use the same compiler version for all modules. However, the rules for dynamic linking with cross-module heap access remain. You must use dynamic linking against the same single version of the runtime.
显然,问题在于插件和主应用程序使用不同且不兼容的堆管理器,这些管理器会破坏彼此的数据结构。理论上,使用动态 CRT 会强制两者使用相同的 CRT,因此两者自动兼容。
在一般情况下,最好让插件负责分配和删除它使用的所有内存。这意味着可能会向插件添加 API,以删除其先前创建并传递回主应用程序的对象。这还为插件和应用程序之间提供了良好的隔离,允许插件出于性能或其他原因使用专门的分配器。例如,这就是 COM 所做的事情。
Obviously, the problem is that the plug-in and main app use different and incompatible heap managers that clobber each other's data structures. Using a dynamic CRT theoretically forces both to use the same CRT and therefore both automatically are compatible.
In the general case, it might be best to have the plug-in be responsible for both allocating and deleting all memory it uses. This implies possibly adding APIs to the plug-in to delete objects it previously created and passed back to the main application. This also provides good isolation between the plug-in and the app, allowing the plug-in to use specialized allocators for performance or other reasons. This is what COM does, for instance.
分配/释放内存的函数是成对的;你不能调用 my_malloc() 然后使用 free(),或者调用 C++ 的“new”运算符,然后从某个随机库调用 FreeMem() :)
你的插件需要一种众所周知的分配和释放内存的方法。如果它执行 malloc(),那么您的主程序可能只执行 free()。但如果它做了一些更奇特的事情(Windows 有大量可用的内存分配器),您的插件 API 需要提供一种方法让主 exe 调用插件以释放其数据。
因此,如果您的主程序调用
,那么您的插件 API 最好有一个
主程序可以明确使用的对应 API。
Functions to allocate/free memory are paired; you can't call my_malloc() and then use free(), or call C++'s "new" operator and later call FreeMem() from some random library :)
Your plugin needs a well-known way of allocating and freeing memory. If it does malloc(), then your main program can probably just do free(). But if it does something more exotic (Windows has tons of memory allocators available), your plugin API needs to provide a way for the main exe to call into the plugin to free its data.
So if your main program calls
then it would be wise for your plugin API to have a corresponding
that the main program can use unambiguously.