C++11 无法清除共享\u ptr泄漏的递归解析代码

C++11 无法清除共享\u ptr泄漏的递归解析代码,c++11,memory-leaks,shared-ptr,C++11,Memory Leaks,Shared Ptr,我在生产代码中广泛使用shared_ptr,主要是为了减少复杂性和维护,它通常工作正常。然而,我已经为一个复杂的元语法编写了一个解析器,它在退出时留下共享对象。罪魁祸首之一是递归性。由于解析代码本身是复杂的,所以我希望在每次进入下一个级别时重复使用它。因此,在执行子代解析时,我将当前元素保存在其父元素的元素中。但这导致了太多剩余的强力裁判的问题。我在弱存储和强存储方面做了很多实验,TreeVect使用弱ptr,但是父分配问题仍然存在。我的问题是,如何去掉在下面的parent语句赋值中添加的第二个

我在生产代码中广泛使用shared_ptr,主要是为了减少复杂性和维护,它通常工作正常。然而,我已经为一个复杂的元语法编写了一个解析器,它在退出时留下共享对象。罪魁祸首之一是递归性。由于解析代码本身是复杂的,所以我希望在每次进入下一个级别时重复使用它。因此,在执行子代解析时,我将当前元素保存在其父元素的元素中。但这导致了太多剩余的强力裁判的问题。我在弱存储和强存储方面做了很多实验,TreeVect使用弱ptr,但是父分配问题仍然存在。我的问题是,如何去掉在下面的parent语句赋值中添加的第二个强ref?下面是说明我的问题的代码:

#include "stdafx.h"
#include <memory>
#include <vector>

struct Tree;
typedef std::weak_ptr< Tree > TreeWptr;
typedef std::shared_ptr< Tree > TreeSptr;
typedef std::vector< TreeWptr > TreeVect;

struct Tree
{
  TreeVect treeVect;
  //TreeSptr parent;
  TreeWptr parent; // changed from strong to weak ptr
};

struct Element1 : public Tree
{
};

struct Element2 : public Tree
{
};


int main()
{
  TreeSptr element1 = std::make_shared< Element1 >();
  TreeSptr element2 = std::make_shared< Element2 >();
  //element2->parent = element1; // illustrates recursive case.  ERROR: Adds extra strong ref to element1
  //element2->parent->treeVect.push_back( element2 );
  element2->parent = element1; // no longer adds extra strong ref to element1
  element2->parent.lock()->treeVect.push_back( element2 );

    return 0;
}
#包括“stdafx.h”
#包括
#包括
结构树;
typedef std::弱_ptrTreeWptr;
typedef std::shared_ptrTreeSptr;
typedef std::vectorTreeVect;
结构树
{
特列维特特列维特;
//TreeSptr亲本;
TreeWptr parent;//从强ptr更改为弱ptr
};
结构元素1:公共树
{
};
结构元素2:公共树
{
};
int main()
{
TreeSptr element1=std::使_共享();
TreeSptr element2=std::使_共享();
//element2->parent=element1;//演示了递归大小写。错误:向element1添加额外的强引用
//element2->parent->treeVect.push_back(element2);
element2->parent=element1;//不再向element1添加额外的强引用
element2->parent.lock()->treeVect.push_back(element2);
返回0;
}

注意:我解决了这个示例程序的问题,将父成员从共享\u ptr更改为弱\u ptr。

没有人对我正在做的事情进行过实质性的权衡,因此我应用了迄今为止我所知道的关于智能指针的知识:永远不要超过对象的一个强引用范围,否则它不会破坏。现在看来很明显

使用SHARED_PTR实现递归解析器的结果

成功!仅供参考,以下是我在解决问题时使用的做法:

1) 开始规划项目时,通常不考虑使用弱PTR。让一切都共享。你需要把注意力完全集中在解决手头的项目上,不要分心。也就是说,在完成之前不要尝试优化。这可以避免由于ptr逻辑而导致的工程代码怪异。顺便说一句,下一次您将更好地估计您的对象在开始时应该拥有的所有权属性

2) 使用内存泄漏检测器程序。我总是用C++ MFC编写,它会自动报告每个运行过程中的泄漏和内存块,因此很容易追踪罪犯。p> 3) 当您对程序感到满意时,为了消除漏洞,请重新考虑对象的所有权,以便在执行路径的末尾有一个强引用指向要自动销毁的顶级对象

使用shared_ptr的一个副作用是代码变得更简单。这是c++11设计人员向我们承诺的,这是真的。错误消息迫使我在编译时仔细考虑每个对象的所有权。在析构函数中,我只是测试指针是否为非null,然后执行删除操作,希望其他线程完成,这样的日子一去不复返了


有一点需要注意:我没有对已过期的弱ptr实施try/catch。我需要为生产代码这样做。我会在这里汇报的。

shared\u ptr
很少让资源管理更简单
unique_ptr
使事情变得更简单,但显然不允许您执行上述操作。在任何情况下,你的问题都不能真正提出问题。我将问题添加到我的OP测试中。在上面的代码中没有数据结构的递归。因此,您真正的代码将是不同的。当你像那样递归时,你知道你像那样递归吗?由于你的叶子似乎保持着它们的父母在身边(而不是相反),如果剩下的叶子有一个不是强引用的父母指针,该怎么办?您的一般问题仍然存在:您认为
shared\u ptr
s可以简化生命周期管理。一般来说,这是一个相当广泛的断言,智能指针,即引用的计数技术,用于新的C++ 11习语,如SyddY-PTR,一般不简化寿命管理,因为这是在C++中被教导的中心主题。这是新的普遍共识吗?我在解决计数问题上没有问题,但从长远来看,这个习惯用法必须解决像我这样的大型系统中的一些重大生命周期管理问题。