关于智能指针内存泄漏的一点点疑问?

SureGOGOGO 2016-10-14 11:50:20

其实,我只是想不懂这程序为啥会内存泄漏,我单步过了,知道是哪一句导致的,但是想不懂。。。
// fg.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include<string>
#include<iostream>
using namespace std;
template<class T>
class share
{
public:
share():point(0),pcount(NULL){}
share(T* p1)
{
pcount=new int(0);
point = p1;
if (pcount == NULL)
{
pcount = new int(1);
}
}
~share()
{
if(--(*pcount) == 0)
{
delete point;
delete pcount;
pcount = NULL;
cout << "begin to delete share" << endl;
point = NULL;
}
}
share(share& t2)
{
point = t2.point;
(*t2.pcount)++;
pcount = t2.pcount;
}
share& operator =(share& t2)
{
if (--(*pcount) == 0)
{
delete point;
}
point = t2.point;
t2.(*pcount)++;
cout<<t2.(*pcount)<<endl;
cout<<*(t2.pcount)<<endl;
pcount = t2.pcount;
return *this;
}
T* operator ->()
{
return point;
}
private:
T* point;
int* pcount; //应该用boost::detail::atomic_count
};

class A
{
public:
A()
{
n = 0;
}
int n;
char v[4];

};

int main()
{
share<A> sp(new(std::nothrow) A());
sp->n = 10;
cout << "sp->n is :" << sp->n << endl;

share<A> sp2 = sp;
sp2->n = 20;
cout << "sp->n is :" << sp2->n << endl;
return 0;
}


在初始化时候我想采用的是
 share():point(0),pcount( new int(0)){}  
这种方式初始化,但是pcount每次都初始化失败,为空的。另外在析构函数这里
  ~share()  
{
if(--(*pcount) == 0)
{
delete point;
delete pcount;
pcount = NULL;
cout << "begin to delete share" << endl;
point = NULL;
}
}
这样就会奔溃,程序已经执行完了,明显是内存泄漏奔溃,但是把单步后定位在
 if(--(*pcount) == 0)
 if(--(*pcount) == 0) 
改成
 if((*pcount) == 0)
这样就不会奔溃,纳闷了,假如不--,下面的就没办法执行,就没有释放,程序就不奔溃。。。

...全文
244 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
Saleayas 2016-10-14
  • 打赏
  • 举报
回复
count 应该和指针一起绑定。 你的count 属于每一个share,而不属于每一个 指针。
jiqiang01234 2016-10-14
  • 打赏
  • 举报
回复
自己造轮子?
AlbertS 2016-10-14
  • 打赏
  • 举报
回复
引用 1 楼 shihengzhen101 的回复:
分开写行不行

~share()  
{  
	if((*pcount) == 0)  
	{  
		delete point;  
		delete pcount;  
		pcount = NULL;  
		cout << "begin to delete share" << endl;  
		point = NULL;  
	}  
	else
	{
		--pcount;
	}
}
我错了
AlbertS 2016-10-14
  • 打赏
  • 举报
回复
分开写行不行

~share()  
{  
	if((*pcount) == 0)  
	{  
		delete point;  
		delete pcount;  
		pcount = NULL;  
		cout << "begin to delete share" << endl;  
		point = NULL;  
	}  
	else
	{
		--pcount;
	}
}
SureGOGOGO 2016-10-14
  • 打赏
  • 举报
回复
收获挺大的,结贴,结贴。
SureGOGOGO 2016-10-14
  • 打赏
  • 举报
回复
引用 11 楼 fefe82 的回复:
原地构造要用 new(this) share(t1); this->share::share(t1); 是不行的。
SureGOGOGO 2016-10-14
  • 打赏
  • 举报
回复
引用 9 楼 dustpg 的回复:
// 改了一下, 说几点:
// 1. 使用c++11的一些特性, 初学者一开始就学好
// 2. 使用类的构造初始化列表构造对象是一个好习惯
// 3. 复制构造函数的参数是const T&, 不要忘了
// 4. 既然提供了默认构造函数使指针为空, 为什么在析构函数里面以至其他函数都不判断一下?
// 5. c++允许手动调用析构/构造函数, 让operator=写法便利了不少
// 6. 既然知道有std::nothrow 那一步判断是否指针为空不明所以
// 7. 注释上写了最好使用原子操作, 为什么不写进模板参数, 这样我单线程使用就不用原子操作了

#include <string>
#include <iostream> 

template<class T, class U> class share
{
public:
    share() :point(nullptr), pcount(nullptr) {}
    share(T* p) : point(p), pcount(new U(1)) { }
    ~share() {
        if (!this->pcount) return;
        if (!--(*pcount)) {
            delete point;
            delete pcount;
            //cout << "begin to delete share" << endl;
        }
    }
    share(const share& t2) noexcept : point(t2.point), pcount(t2.pcount) {
        if (this->pcount) (*this->pcount)++;
    }
    share(share&& t2) noexcept : point(t2.point), pcount(t2.pcount) {
        t2.point = nullptr;
        t2.pcount = nullptr;
    }
    share& operator =(share&& t2) noexcept {
        this->share::~share();
        this->share::share(std::move(t2));
        return *this;
    }
    share& operator =(const share& t2) noexcept {
        this->share::~share();
        this->share::share(t2);
        return *this;
    }
    T* operator ->() noexcept { return point; }
private:
    T*      point;
    U*      pcount;
};

class A
{
public:
    A()
    {
        n = 0;
    }
    int n;
    char v[4];

};

int main()
{
    share<A, int> sp(new(std::nothrow) A());
    sp->n = 10;
    std::cout << "sp->n is :" << sp->n << std::endl;

    share<A, int> sp2 = sp;
    sp2->n = 20;
    std::cout << "sp->n is :" << sp2->n << std::endl;
   return 0;
}
大神,膜拜
fefe82 2016-10-14
  • 打赏
  • 举报
回复
原地构造要用 new(this) share(t1); this->share::share(t1); 是不行的。
SureGOGOGO 2016-10-14
  • 打赏
  • 举报
回复
引用 2 楼 shihengzhen101 的回复:
[quote=引用 1 楼 shihengzhen101 的回复:] 分开写行不行

~share()  
{  
	if((*pcount) == 0)  
	{  
		delete point;  
		delete pcount;  
		pcount = NULL;  
		cout << "begin to delete share" << endl;  
		point = NULL;  
	}  
	else
	{
		--pcount;
	}
}
我错了[/quote] 你没错,写错而而已,
~share()  
{  
	if((*pcount) == 0)  
	{  
		delete point;  
		delete pcount;  
		pcount = NULL;  
		cout << "begin to delete share" << endl;  
		point = NULL;  
	}  
	else
	{
		---(*pcount);
	}
}
问题解决了,我知道问题所在了,我没判断就先--了,其实我的shaer
引用 8 楼 fefe82 的回复:
t2.(*pcount) 是什么 ...
这个是错的,其实我也不知道为啥编译器不报错,所以我留着。。。
dustpg 2016-10-14
  • 打赏
  • 举报
回复
// 改了一下, 说几点:
// 1. 使用c++11的一些特性, 初学者一开始就学好
// 2. 使用类的构造初始化列表构造对象是一个好习惯
// 3. 复制构造函数的参数是const T&, 不要忘了
// 4. 既然提供了默认构造函数使指针为空, 为什么在析构函数里面以至其他函数都不判断一下?
// 5. c++允许手动调用析构/构造函数, 让operator=写法便利了不少
// 6. 既然知道有std::nothrow 那一步判断是否指针为空不明所以
// 7. 注释上写了最好使用原子操作, 为什么不写进模板参数, 这样我单线程使用就不用原子操作了

#include <string>
#include <iostream> 

template<class T, class U> class share
{
public:
    share() :point(nullptr), pcount(nullptr) {}
    share(T* p) : point(p), pcount(new U(1)) { }
    ~share() {
        if (!this->pcount) return;
        if (!--(*pcount)) {
            delete point;
            delete pcount;
            //cout << "begin to delete share" << endl;
        }
    }
    share(const share& t2) noexcept : point(t2.point), pcount(t2.pcount) {
        if (this->pcount) (*this->pcount)++;
    }
    share(share&& t2) noexcept : point(t2.point), pcount(t2.pcount) {
        t2.point = nullptr;
        t2.pcount = nullptr;
    }
    share& operator =(share&& t2) noexcept {
        this->share::~share();
        this->share::share(std::move(t2));
        return *this;
    }
    share& operator =(const share& t2) noexcept {
        this->share::~share();
        this->share::share(t2);
        return *this;
    }
    T* operator ->() noexcept { return point; }
private:
    T*      point;
    U*      pcount;
};

class A
{
public:
    A()
    {
        n = 0;
    }
    int n;
    char v[4];

};

int main()
{
    share<A, int> sp(new(std::nothrow) A());
    sp->n = 10;
    std::cout << "sp->n is :" << sp->n << std::endl;

    share<A, int> sp2 = sp;
    sp2->n = 20;
    std::cout << "sp->n is :" << sp2->n << std::endl;
   return 0;
}
fefe82 2016-10-14
  • 打赏
  • 举报
回复
t2.(*pcount) 是什么 ...
SureGOGOGO 2016-10-14
  • 打赏
  • 举报
回复
引用 4 楼 Saleayas 的回复:
count 应该和指针一起绑定。 你的count 属于每一个share,而不属于每一个 指针。
Help,what should i do?
SureGOGOGO 2016-10-14
  • 打赏
  • 举报
回复
引用 3 楼 jiqiang01234 的回复:
自己造轮子?
造轮子的目的不是为了造轮子,而是更好的理解问题。
SureGOGOGO 2016-10-14
  • 打赏
  • 举报
回复
引用 2 楼 shihengzhen101 的回复:
[quote=引用 1 楼 shihengzhen101 的回复:] 分开写行不行

~share()  
{  
	if((*pcount) == 0)  
	{  
		delete point;  
		delete pcount;  
		pcount = NULL;  
		cout << "begin to delete share" << endl;  
		point = NULL;  
	}  
	else
	{
		--pcount;
	}
}
我错了[/quote] 额

64,643

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧