我的struct的shared_ptr成员指向struct的实例?

时间:2013-11-30 23:29:59

标签: c++ boost struct shared-ptr

我是(升级)共享指针的新手,我正在尝试在代码中测试一些我不想为此目的自下而上重写的内容。

事实证明,当使用其中一个结构 StructA并且成员变量shared_ptr<StructA> foo指向结构的实例时,我可以非常优雅地解决我的问题宾语。

这是简化的结构:

struct StructA {
  vars...
  funcs ...
  shared_ptr<StructA> foo;
};

这导致自我重置错误的问题,所以我试图撤消这个技巧,但它不起作用:

// <their code> (simplified)
StructA lp;
lp.SomePreparation(...);

for-loop () {

  lp.SetSomething(...);
  // my test
  lp.foo.reset(&lp);

  // <their large code section which I'd rather not touch...> 
  // which now works elegantly :)

  // A: doing nothing here, will result in self-reset assertation when 
  //    hitting the `reset(&lp)` above again in the loop. Detailed error below.
  lp.foo.reset(); // B: doing this here, results in glibc double free
  lp.foo.reset(new StructA()); // C: so does this

  // lp.foo = NULL; // what I'd do to a pointer in C.
}

没有调用foo.reset():自复位错误

mybin: include/boost/smart_ptr/shared_ptr.hpp:397: void boost::shared_ptr<T>::reset(Y*) [with Y = StructA, T = StructA]: Assertion `p == 0 || p != px' failed.
Aborted

调用foo.reset():

*** glibc detected *** mybin: double free or corruption (out): 0x00007fff974b3a30 ***
======= Backtrace: =========
/lib64/libc.so.6[0x342b6760e6]
/lib64/libc.so.6[0x342b678c13]
mybin(_ZN5boost14checked_deleteIN1214StructAEEEvPT_+0x26)[0xdd7dfd]
mybin(_ZN5boost6detail17sp_counted_impl_pIN1214LStructAEE7disposeEv+0x1c)[0xdd8b9a]
mybin(_ZN5boost6detail15sp_counted_base7releaseEv+0x42)[0xcedf54]
mybin(_ZN5boost6detail12shared_countD1Ev+0x27)[0xcee017]
mybin(_ZN5boost10shared_ptrIN1214StructAEED1Ev+0x1c)[0xd2dc38]
mybin(_ZN5boost10shared_ptrIN12C14StructAEE5resetEv+0x5b)[0x149b3a9]
....

3 个答案:

答案 0 :(得分:2)

您正尝试将共享指针指向自动变量的实例。这将导致调用delete内存不是“在堆上”。为此,您必须为自定义删除器提供模板参数(例如,无操作删除程序)。

StructA lp; // automatic variable
lp.SomePreparation(...);
...
lp.SetSomething(...);
// my test
lp.foo.reset(&lp); // This is your problem!
...
lp.foo.reset(); // (1)
lp.foo.reset(new StructA()); // (2)

(1)(2)将尝试删除当前指向的对象。对于自动变量,这是一个问题,因为当它超出范围时会自动删除。

答案 1 :(得分:0)

不确定您实际尝试实现的目标,但无法将局部变量的地址传递给boost :: shared_ptr。如果没有shared_ptr指向它并且ofc销毁基于堆栈的变量不是一个好主意,boost :: shared_ptr会破坏其包含的对象。

你想要完成什么?

答案 2 :(得分:0)

这似乎是一个坏主意。虽然更加不方便的解决方案是复制对象。

StructA lp;
lp.SomePreparation(...);
...
lp.SetSomething(...);
// my test
lp.foo.reset(new StructA());
lp.foo->var1 = lp.var1;
lp.foo->var2 = lp.var2; 


... more code