【发布时间】:2021-12-19 09:43:12
【问题描述】:
注意:这个问题与weak_ptr的使用有关,但与包装weak_ptrs无关。
我目前正在评估 Swig,我发现客户端语言在使用包装器时存在“不便”,我没有在网上找到描述,也没有令人满意的解决方案。
在 C++ 中,如果您有一个使用 shared_ptrs 管理的复杂对象图,则必须特别注意该图何时可以具有循环(即,如果它不是 DAG),否则您将get memory leaks。我的意思是如果你必须(无法避免)有一个循环,它必须至少包含一个weak_ptr。这意味着您将不得不处理无法锁定weak_ptr 的情况,因为相关的shared_ptr 已经死亡。这种管理是 C++ 程序员可以用来处理的。现在让我们看看包装器的用户会发生什么:
那么我们来看下面的例子:
- 对象 a,由一个 shared_ptr 持有,有一个 shared_ptr 到 b
- 由 shared_ptr 持有的对象 b 与 a 有一个 weak_ptr
包装器的用户可能会发生以下情况:
A a
B b = a->GetB()
// here let's suppose that a gets out of scope, so it can be garbage collected
b->GetA() // fails if a has been garbage collected
可以通过将 C++ 异常传播到客户端代码(如果无法锁定 weak_ptr 以创建 shared_ptr,则抛出)干净地管理故障。然而,这对于 Python/C#/Java 用户来说并不习惯:他们除了必须手动保持某些对象处于活动状态才能访问其他对象。
我有一个替代解决方案的草稿,其中涉及创建对象 a 和 b 的 C++“共同所有者”,当通过包装器访问 a 或 b 中的任何一个时,SWIG 包装器将锁定该对象 a 和 b,从而保持两者当通过包装器访问它们中的任何一个时,a 和 b 还活着。缺点是这开始看起来像我在 C++ 中实现一个 proto-garbage-collection,这也修改了对象 a 和 b 的 C++ 实现和 API,最后对象 a 和 b 必须由包装器通知它们是通过包装器使用的(我认为如果不修补 SWIG 以在阴影对象的构造函数和析构函数中添加函数调用??)。
我错过了什么吗?这个问题还有其他解决方案吗?
【问题讨论】:
-
这个问题还有其他解决方案吗? 如果问题的意思是我怎样才能让我的代码表现得好像它有垃圾收集一样,那么滚动你自己的垃圾收集是可能是要走的路。
标签: c++ garbage-collection swig weak-references weak-ptr