为外部dll上的缓冲区分配内存并在主应用程序上使用它是否安全?

时间:2010-01-28 13:54:37

标签: c++ c dll malloc

正如在主题中..我在一个应用程序中找到了类似的东西。在主C应用程序中,我们有声明:

void* buff = NULL;

以后有一个电话:

ReadData(&buff);
SaveToFile(buff);

SaveToFile()是来自main函数的C函数。

ReadData(void* * )是来自外部dll的C ++函数。在此函数中,缓冲区的内存由malloc函数分配,并以数据形式存档。

所以这是我的问题:这是正确的吗?

6 个答案:

答案 0 :(得分:12)

正在运行的进程中的所有模块共享相同的地址空间(不关心您是Windows还是Linux或其他任何实际情况,这是一个常见原则)。但是,要小心:从模块A读取或写入模块B拥有的缓冲区很好 - 但释放缓冲区可能不好。

在Windows上,它取决于应用程序链接的运行时库。如果它不是DLL运行时('multithreaded dll'),则每个模块都维护自己的堆管理器副本。因此,分配内存区域的模块也必须负责销毁它,因为只有它自己的堆管理器才知道它。如果您遵循此指南,您将不会遇到问题(链接DLL运行时可以避免此问题,因为所有模块都处理驻留在msvXXXnnn.dll中的某个堆管理器,但会引起其他问题)。

编辑:

  

ReadData(void * *)是来自外部dll的C ++函数。在此函数中,缓冲区的内存由malloc函数分配并存储数据。

这可能会遇到上述分配器问题。向该DLL添加另一个函数(FreeData),它明确地负责释放缓冲区(由Neil Butterworth提出)并且只调用它自己的free()。或者你添加一个DLL函数来查询缓冲区的大小,预先分配它并将其传递给ReadData(这是最干净的选择)。

答案 1 :(得分:2)

如果DLL和主可执行文件都链接到相同的C运行时,这没关系,您可以在指针上调用free()来释放它。但是,更好的想法是在DLL中提供一个释放数据的函数FreeData(void *)。通过这种方式,所有内存管理都在DLL的上下文中完成。

答案 2 :(得分:2)

这很安全。但是,您应该始终检查:

  • 如果同一分配器用于分配和解除分配
  • 负责释放(因此没有意外)
  • 注意任何类型的自动内存管理(如果它是普通的C / C ++那么它没问题)。

答案 3 :(得分:1)

这取决于设计的意图和图书馆所针对的用户。更好的方法是采用一些固定大小的缓冲区并填充并返回。但是,在释放缓冲区时应该小心。最好调用第三方DLL本身提供的自由函数(如果有的话),而不是从主函数中调用free。

对于Windows,如果您的第三方DLL使用不同的堆,并且您的应用程序使用的是其他堆,则可能会导致未定义的行为。对于Ex:如果您的第三方DLL是使用VC8构建的,并且您的应用程序是使用VC6构建的,那么如果您释放外部DLL分配的内存,则会导致问题。

答案 4 :(得分:0)

是的,这是正确的。在该过程中,所有模块(EXE和DLL)都可以同时访问进程中的内存。

答案 5 :(得分:0)

是的,这没有问题。