关于“循环参考",我使用了weak_ptr,但是仍然发生内存泄漏 [英] About "circular reference", I used weak_ptr but memory leak still happened

查看:257
本文介绍了关于“循环参考",我使用了weak_ptr,但是仍然发生内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我读到

与shared_ptr?

我知道我需要使用 weak_ptr 来避免循环引用.

I know that I need to use weak_ptr to avoid circular reference .

所以我创建了一个小程序来播放循环参考.

So I created a little program to play circular reference.

以下对象(间谍)将被调用

Following object(spyder) will be invoke

class spyder {
 public:
  spyder(std::string _name): 
    m_name(_name), finger(nullptr)
  {  }
  inline const std::string ask_name() const{
    return m_name;
  }
  std::shared_ptr<spyder> finger;
 private:
  std::string m_name;
};

我在我的主代码中使用shared_ptr和weak_ptr调用 spyder :

I invoke spyder in my main code with shared_ptr and weak_ptr:

int main(){
  auto sA = std::make_shared<spyder>("A");
  auto sB = std::make_shared<spyder>("B");
  std::weak_ptr<spyder> wp_sA(sA);
  std::weak_ptr<spyder> wp_sB(sB);  
  sA->finger = wp_sB.lock();
  sB->finger = wp_sA.lock();
}

以上代码发生内存泄漏(使用valgrind检查).

Above code has memory leak happened(use valgrind to check).

==20753== Memcheck, a memory error detector
==20753== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==20753== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==20753== Command: ./t
==20753== 
==20753== 
==20753== HEAP SUMMARY:
==20753==     in use at exit: 128 bytes in 2 blocks
==20753==   total heap usage: 3 allocs, 1 frees, 72,832 bytes allocated
==20753== 
==20753== LEAK SUMMARY:
==20753==    definitely lost: 64 bytes in 1 blocks
==20753==    indirectly lost: 64 bytes in 1 blocks
==20753==      possibly lost: 0 bytes in 0 blocks
==20753==    still reachable: 0 bytes in 0 blocks
==20753==         suppressed: 0 bytes in 0 blocks
==20753== Rerun with --leak-check=full to see details of leaked memory
==20753== 
==20753== For counts of detected and suppressed errors, rerun with: -v
==20753== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

但是我将上面的代码修改为:

But after I modify above code as:

int main(){
  spyder sA("A"), sB("B");
  std::weak_ptr<spyder> wp_sA( std::make_shared<spyder>("A") ) ;
  std::weak_ptr<spyder> wp_sB( std::make_shared<spyder>("B") );
  sA.finger = wp_sB.lock();
  sB.finger = wp_sA.lock();
}

没有发生内存泄漏,

==20695== Memcheck, a memory error detector
==20695== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==20695== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==20695== Command: ./t
==20695== 
==20695== 
==20695== HEAP SUMMARY:
==20695==     in use at exit: 0 bytes in 0 blocks
==20695==   total heap usage: 3 allocs, 3 frees, 72,832 bytes allocated
==20695== 
==20695== All heap blocks were freed -- no leaks are possible
==20695== 
==20695== For counts of detected and suppressed errors, rerun with: -v
==20695== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

对此我感到困惑.

推荐答案

您根本没有解决循环依赖项.

sAshared_ptr管理,并将shared_ptr存储到sB. sB依次由shared_ptr管理,并将shared_ptr存储到sA.这意味着他们的引用计数永远不能为0.

sA is managed by a shared_ptr and it stores a shared_ptr to sB. sB in turn is managed by shared_ptr and stores a shared_ptr to sA. This means their reference count can never go to 0.

相反,finger应该是std::weak_ptr类型,并且只应在使用前先使用lock().

Instead, finger should be of type std::weak_ptr and you should only lock() it before you need to use it.

class spyder {
 public:
  spyder(std::string _name): 
    m_name(_name), finger()
  {  }
  inline const std::string ask_name() const{
    return m_name;
  }
  std::weak_ptr<spyder> finger;
 private:
  std::string m_name;
};

int main(){
  auto sA = std::make_shared<spyder>("A");
  auto sB = std::make_shared<spyder>("B");
  sA->finger = sB;
  sB->finger = sA;
}


您的第二个版本

从临时shared_ptr构造weak_ptr,这意味着在构造之后,您的weak_ptr就是expired(). sA.fingersB.finger都在此版本中存储nullptr(但没有内存泄漏).


Your second version

constructs weak_ptr from a temporary shared_ptr, which means immidiately after construction your weak_ptr is expired(). Both sA.finger and sB.finger store nullptr in this version (but there's no memory leak).

这篇关于关于“循环参考",我使用了weak_ptr,但是仍然发生内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆