我的程序架构涉及插件(dll)和exe(显然)。我们是唯一的插件提供商。有人告诉我,如果我们静态链接c运行时,在插件中分配内存然后在exe代码中释放它是一个潜在的问题。但是,如果我们动态链接它,那么只有一个堆,并且c运行时可以访问所有堆。我们根据这个建议切换到动态链接,但是我们从交换机中看到的所有都是令人头疼的问题,并且与新运行时的分发和安装有关。 (在内存分配问题方面,不知道我们避免。)
内存分配有何影响?假设一个插件分配内存,exe释放它。静态与动态链接的c运行时之间是否存在不同的行为?如果我们使用插件,我们是否会在静态链接c运行时时遇到问题?如果我们切换回静态链接,是否会破坏内存泄漏检测和崩溃转储报告?
与Which VC++ runtime version do I choose - static or dynamic?具体Which VC++ runtime version do I choose - static or dynamic?
的评论提出的问题一致http://msdn.microsoft.com/en-us/library/abx4dbyh(v=VS.100).aspx也有一些讨论。
答案 0 :(得分:1)
如果要在一个模块中从堆中分配,在另一个模块中释放,则只需动态链接运行时即可。更重要的是,各方必须动态链接相同的运行时。一旦你这样做,那就没有问题了。
现在,对你的插件强加这是一个非常严格的限制,你应该在做之前三思而后行。强制所有插件作者与你一起升级锁定是一个沉重的拼版。我建议您考虑重构您的接口,以便分配始终与单个模块中的解除分配配对。这解除了我上面描述的限制,使插件作者的生活更轻松。
至于为什么你仍然遇到运行时错误,这很难说。我的猜测是并非所有模块都链接到相同版本的运行时。
在评论中,您声明您可以控制所有插件。这意味着我上面讨论的约束不是强加,因为你很容易为所有模块使用相同的编译器版本。但是,仍然存在与跨模块堆访问进行动态链接的规则。您必须对运行时的同一个版本使用动态链接。
答案 1 :(得分:0)
显然,问题在于插件和主应用程序使用不同且不兼容的堆管理器来破坏彼此的数据结构。使用动态CRT理论上强制两者使用相同的CRT,因此两者都是自动兼容的。
在一般情况下,最好让插件负责分配和删除它使用的所有内存。这意味着可能会向插件添加API以删除先前创建的对象并将其传递回主应用程序。这还提供了插件和应用程序之间的良好隔离,允许插件出于性能或其他原因使用专用分配器。例如,COM就是这样做的。
答案 2 :(得分:0)
分配/释放内存的功能是配对的;你不能调用my_malloc()然后使用free(),或者调用C ++的“new”操作符,然后从一些随机库中调用FreeMem():)
您的插件需要一种众所周知的分配和释放内存的方法。如果它确实是malloc(),那么你的主程序可能就是free()。但是如果它做了更奇特的事情(Windows有大量的内存分配器可用),你的插件API需要为主exe提供一种方法来调用插件来释放它的数据。
所以如果您的主程序调用
foo = plugin->allocate_something()
那么你的插件API有一个相应的
是明智的plugin->free_something (foo)
主程序可以明确使用。