【问题标题】:Is it good practice to use std::move over a DLL boundary?在 DLL 边界上使用 std::move 是一种好习惯吗?
【发布时间】:2012-07-19 10:03:52
【问题描述】:

任何在 Windows 上使用过 DLL 的人都会告诉您,在 DLL 边界的一侧new 一个对象然后在另一侧使用delete 这是一个坏主意。通常使用带有 DLL 的工厂方法来避免这种情况,以便执行新建/删除的目标代码出现在同一个目标文件中。

今天,我正在设计一个新接口,我想将std::movestd::vector<std::wstring> 从一个对象传递到另一个对象,其中对象是在不同的 DLL 中创建的。当我想到这可能意味着 delete 现在可能出现在与 new 不同的对象代码中时,我已经准备好这样做了,因为不同的对象现在拥有底层指针。

任何人都可以确认是否是这种情况?

【问题讨论】:

  • move 的注意事项应与 swap 的注意事项相同。
  • 更一般:STL 对象不应通过 Dll 边界。因此,即使不使用 std::move,整个解决方案也是有问题的。
  • @AlexFarber 我在导出的类规则中找不到任何关于标准对象(例如std::vector)的内容,如果您在某处看到过这个链接,您可以发布一个链接吗?
  • 在 dll 可执行文件中创建的 STL 对象不应直接从另一个 exe/dll 访问 - 只能通过创建它的 dll 函数访问。 STL 对象可能是实现的一部分,但不是接口。
  • @AlexFarber:这适用于公共接口。如果您的 Foo 应用程序有一个“FooPrint.DLL”,当用户想要打印某些东西时它会延迟加载,那么使用 STL 就可以了。您提到的知识库文章适用于 Visual Studio 6 及更早版本。那是 14 年前的事了!

标签: c++ dll c++11


【解决方案1】:

一般来说,应该跨越 DLL 边界的唯一对象是析构函数(和复制构造函数/赋值)不做太多事情的对象。最好只使用 POD 来获得最大的安全性(因此允许两个 DLL 进行接口,即使它们不是使用完全相同的编译器的完全相同版本编译的)。

至于移动会发生什么,是的,接收 DLL 将释放由提供 DLL 分配的内存。这通常属于“不好”的阵营。

如果您想让它安全,您可以使用特殊分配器从接收 DLL 分配(和解除分配)内存。但这通常很烦人。

【讨论】:

  • 如果 DLL 可以使用不同的编译器和/或设置和/或标准库编译,则为真。
  • 如何围绕一个智能 prikter 移动,如唯一或共享 ptr?还是一样?
  • @Johan:这些可以工作,但前提是它们具有调用正确 DLL 的显式析构函数。
猜你喜欢
  • 2011-02-28
  • 1970-01-01
  • 2016-05-27
  • 2019-12-11
  • 1970-01-01
  • 1970-01-01
  • 2019-03-06
  • 2013-03-30
  • 2015-09-02
相关资源
最近更新 更多