C运行时静态与动态链接中的内存分配

我的程序架构涉及插件(dll)和exe(显然)。 我们是唯一的插件提供商。 有人告诉我,如果我们静态链接c运行时,在插件中分配内存然后在exe代码中释放它是一个潜在的问题。 但是,如果我们动态链接它,那么只有一个堆,并且c运行时可以访问所有这些堆。 我们根据这个建议切换到动态链接,但是我们从交换机看到的所有内容都是令人头疼的问题,以及与新运行时的分发和安装相关的麻烦。 (不知道我们在内存分配问题上避免了什么。)

内存分配的含义是什么? 假设一个插件分配内存,exe释放它。 静态与动态链接的c运行时之间是否存在不同的行为? 如果我们使用插件,我们是否会在静态链接c运行时时遇到问题? 如果我们切换回静态链接,那会破坏内存泄漏检测和崩溃转储报告吗?

与我选择哪个VC ++运行时版本的注释提出的一些问题一致- 静态还是动态? 具体来说,我选择哪个VC ++运行时版本 – 静态还是动态?

在http://msdn.microsoft.com/en-us/library/abx4dbyh(v=VS.100).aspx上也有一些讨论。

如果要在一个模块中从堆中分配,而在另一个模块中释放,则只需动态链接运行时即可。 而且,所有各方必须动态链接相同的运行时。 一旦你这样做,那就没有问题了。

现在,这是对你的插件强加的严重限制,你应该在做之前三思而行。 强制所有插件作者与你一起升级锁定是一个沉重的强加。 我建议您考虑重构您的接口,以便分配始终与单个模块中的解除分配配对。 这解除了我上面描述的限制,使插件作者的生活更轻松。

至于为什么你仍然遇到运行时错误,这很难说。 我的猜测是并非所有模块都链接到相同版本的运行时。


在评论中,您声明您可以控制所有插件。 这意味着我上面讨论的约束不是强加,因为你很容易为所有模块使用相同的编译器版本。 但是,仍然存在用于跨模块堆访问的动态链接的规则。 必须对运行时的同一单个版本使用动态链接。

分配/释放内存的function是配对的; 你不能调用my_malloc()然后使用free(),或者调用C ++的“new”运算符,然后从一些随机库中调用FreeMem():)

你的插件需要一种众所周知的分配和释放内存的方法。 如果它确实是malloc(),那么你的主程序可能就是free()。 但是如果它做了更具异国情调的东西(Windows有大量的内存分配器可用),你的插件API需要为主exe提供一种方法来调用插件来释放它的数据。

所以,如果您的主程序调用

foo = plugin->allocate_something() 

那么你的插件API有一个相应的明智之举

 plugin->free_something (foo) 

主程序可以毫不含糊地使用。

显然,问题是插件和主应用程序使用不同且不兼容的堆管理器来破坏彼此的数据结构。 使用动态CRT理论上强制两者使用相同的CRT,因此两者都是自动兼容的。

在一般情况下,最好让插件负责分配和删除它使用的所有内存。 这意味着可能会向插件添加API以删除先前创建并传递回主应用程序的对象。 这还提供了插件和应用程序之间的良好隔离,允许插件出于性能或其他原因使用专用分配器。 例如,COM就是这样做的。