shared_ptr 有问题。我无法在没有错误的情况下创建我的结构
Problem with shared_ptr. I cannot create my struct without mistakes
请帮忙找出我的自定义共享指针中的错误class SharedPtr<T>
。我找不到它了。但是代码可以处理泄漏。
我认为 reset 方法或 operator=
方法中的错误。可能不调用这些方法代码就可以工作。我认为是因为 valgrind 没有显示泄漏和错误。但是调用这些方法会显示错误,有时会泄漏
#include <iostream>
#include <algorithm>
#include <memory>
using std::cout;
using std::cin;
using std::endl;
template <typename T>
struct SharedPtr
{
explicit SharedPtr(T *ptr = 0) : p_(ptr), c_(0)
{
if (p_) c_ = new size_t(1);
}
~SharedPtr()
{
if (c_ && --*c_ == 0)
{
delete p_;
delete c_;
}
}
SharedPtr(const SharedPtr &p) : p_(p.get()), c_(p.getc())
{
if (c_) { ++*c_; }
}
SharedPtr& operator=(const SharedPtr &p)
{
p_ = p.p_;
c_ = p.c_;
return *this;
}
T* get() const { return p_;}
size_t* getc() const { return c_; }
size_t getcc() const { return *c_; }
void reset(T *ptr = 0)
{
SharedPtr(ptr).swap(*this);
// if (c_ && --*c_ == 0)
// {
// delete p_;
// delete c_;
// }
// if (ptr == nullptr)
// {
// c_ = nullptr;
// }
// p_ = ptr;
}
T& operator*() const { return *p_;}
T* operator->() const { return p_;}
private:
void swap(SharedPtr& other)
{
std::swap(p_, other.p_);
size_t* tmp = c_;
c_ = other.c_;
other.c_ = tmp;
}
T * p_;
size_t * c_;
};
int main ()
{
SharedPtr<int> p1(new int(5));
SharedPtr<int> p2(new int(10));
SharedPtr<int> p5;
p5 = p2;
p1 = p5;
p1.reset();
}
valgrind 输出:
==12777== HEAP SUMMARY:
==12777== in use at exit: 12 bytes in 2 blocks
==12777== total heap usage: 5 allocs, 3 frees, 72,728 bytes allocated
==12777==
==12777== LEAK SUMMARY:
==12777== definitely lost: 12 bytes in 2 blocks
==12777== indirectly lost: 0 bytes in 0 blocks
==12777== possibly lost: 0 bytes in 0 blocks
==12777== still reachable: 0 bytes in 0 blocks
==12777== suppressed: 0 bytes in 0 blocks
==12777== Rerun with --leak-check=full to see details of leaked memory
==12777==
==12777== For lists of detected and suppressed errors, rerun with: -s
==12777== ERROR SUMMARY: 6 errors from 6 contexts (suppressed: 0 from 0)
还有一个同样的错误:
==12777== Invalid read of size 8
==12777== at 0x1093F9: SharedPtr<int>::~SharedPtr() (in /home/baseoleph/git/stepik/1_7_CPP/a.out)
==12777== by 0x109296: main (in /home/baseoleph/git/stepik/1_7_CPP/a.out)
==12777== Address 0x4da5d70 is 0 bytes inside a block of size 8 free'd
==12777== at 0x483D1CF: operator delete(void*, unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==12777== by 0x10944D: SharedPtr<int>::~SharedPtr() (in /home/baseoleph/git/stepik/1_7_CPP/a.out)
==12777== by 0x1094DA: SharedPtr<int>::reset(int*) (in /home/baseoleph/git/stepik/1_7_CPP/a.out)
==12777== by 0x10928A: main (in /home/baseoleph/git/stepik/1_7_CPP/a.out)
==12777== Block was alloc'd at
==12777== at 0x483BE63: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==12777== by 0x1093C0: SharedPtr<int>::SharedPtr(int*) (in /home/baseoleph/git/stepik/1_7_CPP/a.out)
==12777== by 0x109242: main (in /home/baseoleph/git/stepik/1_7_CPP/a.out)
你的赋值运算符不应该减少 c_ 并可能释放 p_ 吗?
并增加新的 c_ 值;
问题出在operator =
。您应该释放以前的值(如果有)并增加计数。你应该考虑旧的和分配的指向对象相同的特殊情况。
因为您已经有了一个 swap
,您应该只使用 复制和交换 习语,它已知对可能的极端情况具有鲁棒性:
SharedPtr& operator=(const SharedPtr &p)
{
SharedPtr tmp(p);
swap(tmp)
return *this;
}
如果 SharedPtr
不包含任何内容,则 dtor 或临时对象将不执行任何操作,如果它包含一个对象,则 dtor 将正确地递减它并可选择销毁它。如果您分配相同的对象,它也不会造成任何伤害...
请帮忙找出我的自定义共享指针中的错误class SharedPtr<T>
。我找不到它了。但是代码可以处理泄漏。
我认为 reset 方法或 operator=
方法中的错误。可能不调用这些方法代码就可以工作。我认为是因为 valgrind 没有显示泄漏和错误。但是调用这些方法会显示错误,有时会泄漏
#include <iostream>
#include <algorithm>
#include <memory>
using std::cout;
using std::cin;
using std::endl;
template <typename T>
struct SharedPtr
{
explicit SharedPtr(T *ptr = 0) : p_(ptr), c_(0)
{
if (p_) c_ = new size_t(1);
}
~SharedPtr()
{
if (c_ && --*c_ == 0)
{
delete p_;
delete c_;
}
}
SharedPtr(const SharedPtr &p) : p_(p.get()), c_(p.getc())
{
if (c_) { ++*c_; }
}
SharedPtr& operator=(const SharedPtr &p)
{
p_ = p.p_;
c_ = p.c_;
return *this;
}
T* get() const { return p_;}
size_t* getc() const { return c_; }
size_t getcc() const { return *c_; }
void reset(T *ptr = 0)
{
SharedPtr(ptr).swap(*this);
// if (c_ && --*c_ == 0)
// {
// delete p_;
// delete c_;
// }
// if (ptr == nullptr)
// {
// c_ = nullptr;
// }
// p_ = ptr;
}
T& operator*() const { return *p_;}
T* operator->() const { return p_;}
private:
void swap(SharedPtr& other)
{
std::swap(p_, other.p_);
size_t* tmp = c_;
c_ = other.c_;
other.c_ = tmp;
}
T * p_;
size_t * c_;
};
int main ()
{
SharedPtr<int> p1(new int(5));
SharedPtr<int> p2(new int(10));
SharedPtr<int> p5;
p5 = p2;
p1 = p5;
p1.reset();
}
valgrind 输出:
==12777== HEAP SUMMARY:
==12777== in use at exit: 12 bytes in 2 blocks
==12777== total heap usage: 5 allocs, 3 frees, 72,728 bytes allocated
==12777==
==12777== LEAK SUMMARY:
==12777== definitely lost: 12 bytes in 2 blocks
==12777== indirectly lost: 0 bytes in 0 blocks
==12777== possibly lost: 0 bytes in 0 blocks
==12777== still reachable: 0 bytes in 0 blocks
==12777== suppressed: 0 bytes in 0 blocks
==12777== Rerun with --leak-check=full to see details of leaked memory
==12777==
==12777== For lists of detected and suppressed errors, rerun with: -s
==12777== ERROR SUMMARY: 6 errors from 6 contexts (suppressed: 0 from 0)
还有一个同样的错误:
==12777== Invalid read of size 8
==12777== at 0x1093F9: SharedPtr<int>::~SharedPtr() (in /home/baseoleph/git/stepik/1_7_CPP/a.out)
==12777== by 0x109296: main (in /home/baseoleph/git/stepik/1_7_CPP/a.out)
==12777== Address 0x4da5d70 is 0 bytes inside a block of size 8 free'd
==12777== at 0x483D1CF: operator delete(void*, unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==12777== by 0x10944D: SharedPtr<int>::~SharedPtr() (in /home/baseoleph/git/stepik/1_7_CPP/a.out)
==12777== by 0x1094DA: SharedPtr<int>::reset(int*) (in /home/baseoleph/git/stepik/1_7_CPP/a.out)
==12777== by 0x10928A: main (in /home/baseoleph/git/stepik/1_7_CPP/a.out)
==12777== Block was alloc'd at
==12777== at 0x483BE63: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==12777== by 0x1093C0: SharedPtr<int>::SharedPtr(int*) (in /home/baseoleph/git/stepik/1_7_CPP/a.out)
==12777== by 0x109242: main (in /home/baseoleph/git/stepik/1_7_CPP/a.out)
你的赋值运算符不应该减少 c_ 并可能释放 p_ 吗?
并增加新的 c_ 值;
问题出在operator =
。您应该释放以前的值(如果有)并增加计数。你应该考虑旧的和分配的指向对象相同的特殊情况。
因为您已经有了一个 swap
,您应该只使用 复制和交换 习语,它已知对可能的极端情况具有鲁棒性:
SharedPtr& operator=(const SharedPtr &p)
{
SharedPtr tmp(p);
swap(tmp)
return *this;
}
如果 SharedPtr
不包含任何内容,则 dtor 或临时对象将不执行任何操作,如果它包含一个对象,则 dtor 将正确地递减它并可选择销毁它。如果您分配相同的对象,它也不会造成任何伤害...