Valgrind 在嵌套 shared_ptrs 的 =operator 上报告读取错误
Valgrind report read error on =operator with nested shared_ptrs
我有这个简单的代码
#include<memory>
class SLLNode{
public:
SLLNode(const int& d){
data_ = d;
}
std::shared_ptr<SLLNode> next_;
int data_;
};
int main(){
std::shared_ptr<SLLNode> head(new SLLNode(1));
head->next_.reset(new SLLNode(2));
*head = *(head->next_);
return 0;
}
Valgrind 抱怨在我的案例中读取无效。
==17312== Invalid read of size 4
==17312== at 0x108EF3: SLLNode::operator=(SLLNode const&) (test_shared_ptr.cpp:3)
==17312== by 0x108DA3: main (test_shared_ptr.cpp:16)
==17312== Address 0x5b7dd50 is 16 bytes inside a block of size 24 free'd
==17312== at 0x4C3123B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17312== by 0x109511: std::_Sp_counted_ptr<SLLNode*, (__gnu_cxx::_Lock_policy)2>::_M_dispose() (shared_ptr_base.h:376)
==17312== by 0x1090DF: std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() (shared_ptr_base.h:154)
==17312== by 0x109061: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::operator=(std::__shared_count<(__gnu_cxx::_Lock_policy)2> const&) (shared_ptr_base.h:703)
==17312== by 0x108E9A: std::__shared_ptr<SLLNode, (__gnu_cxx::_Lock_policy)2>::operator=(std::__shared_ptr<SLLNode, (__gnu_cxx::_Lock_policy)2> const&) (shared_ptr_base.h:1034)
==17312== by 0x108EC4: std::shared_ptr<SLLNode>::operator=(std::shared_ptr<SLLNode> const&) (shared_ptr.h:93)
==17312== by 0x108EEE: SLLNode::operator=(SLLNode const&) (test_shared_ptr.cpp:3)
==17312== by 0x108DA3: main (test_shared_ptr.cpp:16)
==17312== Block was alloc'd at
==17312== at 0x4C3017F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17312== by 0x108D5C: main (test_shared_ptr.cpp:15)
我使用的命令是:
valgrind --tool=memcheck ./test_shared_ptr
只有当我使用嵌套 shared_ptr 时,= 运算符似乎才会导致此问题。
我期待来自 ptr 头的数据被释放并替换为来自 ptr head.next_ 的数据,但似乎发生了其他事情,因为我有这个无效读取。
我想替换 head 指向的数据(而不是 head 本身),因为这个 head ptr 可能是另一个 shared_ptr head.
的副本
隐式定义的赋值运算符如下所示:
SLLNode& SLLNode::operator=(const SLLNode& other) {
next_ = other.next_;
data_ = other.data_;
return *this;
}
在您的示例中,other
是 SLLNode(2)
,它仅通过来自 head->next_
的引用保持活动状态。 other.next_
是 NULL
.
上面的第一个赋值将 head->next_
设置为 NULL
,这导致 SLLNode(2)
被销毁,并留下 other
悬空引用。下一行通过在对象的生命周期结束后访问对象来展示未定义的行为。
我有这个简单的代码
#include<memory>
class SLLNode{
public:
SLLNode(const int& d){
data_ = d;
}
std::shared_ptr<SLLNode> next_;
int data_;
};
int main(){
std::shared_ptr<SLLNode> head(new SLLNode(1));
head->next_.reset(new SLLNode(2));
*head = *(head->next_);
return 0;
}
Valgrind 抱怨在我的案例中读取无效。
==17312== Invalid read of size 4
==17312== at 0x108EF3: SLLNode::operator=(SLLNode const&) (test_shared_ptr.cpp:3)
==17312== by 0x108DA3: main (test_shared_ptr.cpp:16)
==17312== Address 0x5b7dd50 is 16 bytes inside a block of size 24 free'd
==17312== at 0x4C3123B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17312== by 0x109511: std::_Sp_counted_ptr<SLLNode*, (__gnu_cxx::_Lock_policy)2>::_M_dispose() (shared_ptr_base.h:376)
==17312== by 0x1090DF: std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() (shared_ptr_base.h:154)
==17312== by 0x109061: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::operator=(std::__shared_count<(__gnu_cxx::_Lock_policy)2> const&) (shared_ptr_base.h:703)
==17312== by 0x108E9A: std::__shared_ptr<SLLNode, (__gnu_cxx::_Lock_policy)2>::operator=(std::__shared_ptr<SLLNode, (__gnu_cxx::_Lock_policy)2> const&) (shared_ptr_base.h:1034)
==17312== by 0x108EC4: std::shared_ptr<SLLNode>::operator=(std::shared_ptr<SLLNode> const&) (shared_ptr.h:93)
==17312== by 0x108EEE: SLLNode::operator=(SLLNode const&) (test_shared_ptr.cpp:3)
==17312== by 0x108DA3: main (test_shared_ptr.cpp:16)
==17312== Block was alloc'd at
==17312== at 0x4C3017F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17312== by 0x108D5C: main (test_shared_ptr.cpp:15)
我使用的命令是:
valgrind --tool=memcheck ./test_shared_ptr
只有当我使用嵌套 shared_ptr 时,= 运算符似乎才会导致此问题。 我期待来自 ptr 头的数据被释放并替换为来自 ptr head.next_ 的数据,但似乎发生了其他事情,因为我有这个无效读取。 我想替换 head 指向的数据(而不是 head 本身),因为这个 head ptr 可能是另一个 shared_ptr head.
的副本隐式定义的赋值运算符如下所示:
SLLNode& SLLNode::operator=(const SLLNode& other) {
next_ = other.next_;
data_ = other.data_;
return *this;
}
在您的示例中,other
是 SLLNode(2)
,它仅通过来自 head->next_
的引用保持活动状态。 other.next_
是 NULL
.
上面的第一个赋值将 head->next_
设置为 NULL
,这导致 SLLNode(2)
被销毁,并留下 other
悬空引用。下一行通过在对象的生命周期结束后访问对象来展示未定义的行为。