我是(升级)共享指针的新手,我正在尝试在代码中测试一些我不想为此目的自下而上重写的内容。
事实证明,当使用其中一个结构 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.
}
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
*** 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]
....
答案 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