Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在DLL中分配内存并给客户端应用程序一个指向它的指针,这是一种不好的做法吗?_C++_Design Patterns - Fatal编程技术网

C++ 在DLL中分配内存并给客户端应用程序一个指向它的指针,这是一种不好的做法吗?

C++ 在DLL中分配内存并给客户端应用程序一个指向它的指针,这是一种不好的做法吗?,c++,design-patterns,C++,Design Patterns,我使用的是动态加载DLL的exe。DLL中的函数在堆上分配内存,并将指向该内存的指针传递给exe 一位长者说这样做是不好的做法。他说,如果我必须在exe和DLL之间共享内存,exe必须分配内存并将指向该内存的指针传递给DLL,反之亦然。这是真的吗?为什么? 编辑:在我的例子中,我计划在DLL本身内部分配和释放内存。我认为,交出原始指针通常是不好的做法。对于dll,它应该返回一个智能指针,该指针具有一个适当处理清理的自定义删除程序(选项有std::unique_ptr、std::shared_pt

我使用的是动态加载DLL的exe。DLL中的函数在堆上分配内存,并将指向该内存的指针传递给exe

一位长者说这样做是不好的做法。他说,如果我必须在exe和DLL之间共享内存,exe必须分配内存并将指向该内存的指针传递给DLL,反之亦然。这是真的吗?为什么?


编辑:在我的例子中,我计划在DLL本身内部分配和释放内存。

我认为,交出原始指针通常是不好的做法。对于dll,它应该返回一个智能指针,该指针具有一个适当处理清理的自定义删除程序(选项有
std::unique_ptr
std::shared_ptr
boost::shared_ptr


事实上,使用
std::weak_ptr
boost::weak_ptr
可能更安全—这些要求您在每次访问资源时都要进行检查,因为在此期间dll可能已卸载。

设计模式背后的一个基本思想是所有权。想法是-
创建资源(并因此将其保存在指针中)的人应该负责删除资源。这将确保设计的神圣性,在更长的项目生命周期中,开发人员可以看到更少的bug


所以现在,在您的情况下,DLL可以由任何可执行文件附加,他可以尝试删除资源,这可能会导致未来的问题。因此,我认为有人建议反之亦然,我认为这是一个合理的建议。

我以前见过这个问题,它是由DLL和exe与CRT的链接不同(静态、动态MT等)引起的


我想在DLL和可执行文件之间传递一个指向内存的指针,它们都应该提供某种
Free()
功能来从各自的堆中释放内存。

正如@kumar\u m\u kiran已经指出的,这是关于所有权的问题,但是我想指出,@aleguna也是正确的,因此,imho,正确的规则是“在DLL或EXE中分配和取消分配相同的内存,但不能同时在两者中分配”。

通常,堆(一个堆)属于进程,从何处分配并不重要,因此这将正常工作,除非它不属于进程

因此,认为这是“不良做法”的说法是正确的。没有什么事情比工作正常的事情更糟糕,除非它不工作

最糟糕的是,当一切都爆发时,并不是马上就能看出哪里出了问题,你很容易在不知情的情况下遇到问题。这可能很容易,就像将特定版本的CRT链接到DLL中一样。或者您团队中的某个人可能出于某种原因创建了一个单独的堆。或者,其他一些不明显的原因导致了另一个堆的创建

使“从错误堆中释放”的情况如此恶劣的原因是,您通常不知道将发生什么,或者何时发生(或者是否有人会注意到)

您可能会从堆函数或异常中获得NULL返回值。您的应用程序可能已经为它们中的任何一个做好了准备,也可能没有(老实说,您总是检查返回值,不是吗?)。它可能会在释放后立即崩溃,或者您可能只是在几分钟或几小时后悄悄泄漏内存并耗尽地址空间(或内存),没有人会知道原因。或者是别的什么。

因此,您所看到的可能与导致问题的原因完全不相关。

exe和dll可能有不同的堆。当一方尝试释放另一方分配的内存时,释放失败,出现泄漏

只有当exe和dll都动态使用CRT,并且使用相同版本的CRT时,它们才使用相同的堆


因此,在同一个二进制文件中进行分配和释放是一个非常好的建议。

这不一定是不好的做法,但这是危险的做法(可能是不好的)。你需要仔细考虑谁负责释放记忆。exe可能无法(或不应该能够)直接释放DLL的内存,因此可能会在以后的某个日期将此指针传递回DLL。因此,现在我们在EXE和DLL之间来回传递一个指针,这不太好。

以下是让调用方提供指针的一些原因:

  • 对称所有权语义。其他几个答案已经解释了这一点
  • 避免分配器和deallocator不匹配。如中所述,如果DLL分配指针并返回它,调用方必须调用相应的deallocator来释放它。这不一定是无关紧要的:DLL可能是静态链接到一个版本的,例如,
    malloc
    /
    free
    ,而
    .exe
    是链接到另一个版本的
    malloc
    /
    free
    。(例如,DLL可能使用发布版本,而
    .exe
    使用专门的调试版本。)
  • 灵活性。如果DLL是供一般使用的,让调用方分配内存会给调用方更多的选择。假设调用者不想使用
    malloc
    ,而是希望从某个特定的内存池分配内存。也许在这种情况下,调用方可以提供指向堆栈上分配的内存的指针。如果DLL本身分配了内存,则调用者没有这些选项中的任何一个

  • (第二和第三点也可以通过使用<代码> .exe < /> >提供DLL代码的分配器/分配器来使用)。(<)/P> < P>我只想指出,<强> >分配器< /强>到DLL分配内存是完全安全的,是C++ STD库本身使用的标准模型。在这种情况下,al