大家看看这段代码是否存在内存泄露

SKATE11 2014-02-26 07:26:04
网上看的一段设计模式 原型模式代码 感觉存在内存泄露 大家看看

/*
原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象
Created by Phoenix_FuliMa
*/

#include <iostream>
#include <string>
using namespace std;


class Prototype
{
public:
virtual Prototype *Clone() = 0;
virtual void display() = 0;
};

class Prototype1:public Prototype
{
protected:
string name;
int id;
public:
Prototype1(string name, int id)
{
this->name = name;
this->id = id;
}
Prototype1(const Prototype1&type)
{
this->name = type.name;
this->id = type.id;
}

virtual void display()
{
cout<<"my name and id are : " << this->id<<" "<< this->name <<endl;
}
Prototype *Clone()
{
return new Prototype1(*this);
}
};

class Prototype2:public Prototype
{
protected:
string name;
public:
Prototype2(string name)
{
this->name = name;
}
Prototype2(const Prototype2&type)
{
this->name = type.name;
}

virtual void display()
{
cout<<"my name is : "<< this->name <<endl;
}
Prototype *Clone()
{
return new Prototype2(*this);
}
};

int main()
{
Prototype *obj1 = new Prototype1("mafuli", 1);
Prototype *obj2 = obj1->Clone();
Prototype *obj3 = obj2->Clone();

obj1->display();
obj2->display();
obj3->display();

Prototype *obj4 = new Prototype2("fulima");
Prototype *obj5 = obj4->Clone();
Prototype *obj6 = obj5->Clone();

obj4->display();
obj5->display();
obj6->display();

delete obj1;
delete obj2;
delete obj3;
delete obj4;
delete obj5;
delete obj6;


system("pause");
return 0;
}
...全文
276 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
menzi11 2014-02-27
  • 打赏
  • 举报
回复
引用 13 楼 SKATE11 的回复:
[quote=引用 12 楼 mujiok2003 的回复:] [quote=引用 9 楼 SKATE11 的回复:] [quote=引用 5 楼 mujiok2003 的回复:] 是一个有缺陷的实现。
#include <iostream>  
#include <string>  
using namespace std;  
  
  
class Prototype  
{  
public:  
#ifdef VD
    virtual ~Prototype() {} 
#endif
    virtual Prototype *Clone() = 0;  
    virtual void display() = 0;  
};  
  
struct Resource
{
  Resource()
  {
    std::cout << "creating resource " << this << std::endl;
  }
  Resource(Resource const& )
  {
    std::cout << "creating resource " << this << std::endl;
  }
  ~Resource()
  {
    std::cout << "destroying resource " << this << std::endl;
  }
};

class Prototype2:public Prototype  
{  
protected:  
    string name;  
    Resource* pr;
public:  
    ~Prototype2()  
    {
      delete pr;
    }
    Prototype2(string name)  
    {  
        this->name = name;  
        pr = new Resource();
    }  
    Prototype2(const Prototype2&type)  
    {  
        this->name = type.name;  
        pr = new Resource(*type.pr);
    }  
  
    virtual void display()  
    {  
        cout<<"my name is : "<< this->name <<endl;  
    }  
    Prototype *Clone()  
    {  
        return new Prototype2(*this);  
    }  
};  
  
int main()  
{  
  
    Prototype *obj4 = new Prototype2("fulima");  
    Prototype *obj6 = obj4->Clone();  
  
    obj4->display();  
    obj6->display();  
      
    delete obj4;  
    delete obj6;  
  
    return 0;  
} 

c:\demo>cl /nologo /EHsc /W4 /DVD demo.cpp
demo.cpp

c:\demo>demo
creating resource 001F7F68
creating resource 001F7FC0
my name is : fulima
my name is : fulima
destroying resource 001F7F68
destroying resource 001F7FC0

c:\demo>cl /nologo /EHsc /W4  demo.cpp
demo.cpp

c:\demo>demo
creating resource 002A7F68
creating resource 002A7FC0
my name is : fulima
my name is : fulima

c:\demo>
其实我的疑问就是 用基类指针 删除派生类new出来的对象 这样是否会存在内存泄露[/quote] 你的例子没有泄露,我的例子中可能泄露了。[/quote] 比如基类占的空间为8字节 派生类占的空间为12字节 那么我用基类指针指向一个派生类new出来的对象 那么在delete的时候是只释放8字节的基类部分呢还是new出来的12字节都释放掉[/quote] free()的释放是按照指针来释放,所以当你p=malloc(X)得到一个尺寸为X的内存块,则最终 当你free(p)它的时候,总是释放掉X尺寸,而不可能释放X/2或者X-1.即使拿基类指针释放 子类对象,最终将按照this的地址释放掉内存不可能只释放8字节而剩下4字节没释放. 这段代码真正的问题是子类中有个string没有被释放掉,string维护着一段内存呢,string不调用 ~string()则这段内存就飞了.所以内存泄露了. 任何可能被其他类继承的类,其析构函数都应该是virtual的,如果一个类的 析构函数不是virtual的说明类设计者不想让你继承它.唯一的特例是父类的析构函数是protected的.
SKATE11 2014-02-27
  • 打赏
  • 举报
回复
引用 12 楼 mujiok2003 的回复:
[quote=引用 9 楼 SKATE11 的回复:] [quote=引用 5 楼 mujiok2003 的回复:] 是一个有缺陷的实现。
#include <iostream>  
#include <string>  
using namespace std;  
  
  
class Prototype  
{  
public:  
#ifdef VD
    virtual ~Prototype() {} 
#endif
    virtual Prototype *Clone() = 0;  
    virtual void display() = 0;  
};  
  
struct Resource
{
  Resource()
  {
    std::cout << "creating resource " << this << std::endl;
  }
  Resource(Resource const& )
  {
    std::cout << "creating resource " << this << std::endl;
  }
  ~Resource()
  {
    std::cout << "destroying resource " << this << std::endl;
  }
};

class Prototype2:public Prototype  
{  
protected:  
    string name;  
    Resource* pr;
public:  
    ~Prototype2()  
    {
      delete pr;
    }
    Prototype2(string name)  
    {  
        this->name = name;  
        pr = new Resource();
    }  
    Prototype2(const Prototype2&type)  
    {  
        this->name = type.name;  
        pr = new Resource(*type.pr);
    }  
  
    virtual void display()  
    {  
        cout<<"my name is : "<< this->name <<endl;  
    }  
    Prototype *Clone()  
    {  
        return new Prototype2(*this);  
    }  
};  
  
int main()  
{  
  
    Prototype *obj4 = new Prototype2("fulima");  
    Prototype *obj6 = obj4->Clone();  
  
    obj4->display();  
    obj6->display();  
      
    delete obj4;  
    delete obj6;  
  
    return 0;  
} 

c:\demo>cl /nologo /EHsc /W4 /DVD demo.cpp
demo.cpp

c:\demo>demo
creating resource 001F7F68
creating resource 001F7FC0
my name is : fulima
my name is : fulima
destroying resource 001F7F68
destroying resource 001F7FC0

c:\demo>cl /nologo /EHsc /W4  demo.cpp
demo.cpp

c:\demo>demo
creating resource 002A7F68
creating resource 002A7FC0
my name is : fulima
my name is : fulima

c:\demo>
其实我的疑问就是 用基类指针 删除派生类new出来的对象 这样是否会存在内存泄露[/quote] 你的例子没有泄露,我的例子中可能泄露了。[/quote] 比如基类占的空间为8字节 派生类占的空间为12字节 那么我用基类指针指向一个派生类new出来的对象 那么在delete的时候是只释放8字节的基类部分呢还是new出来的12字节都释放掉
mujiok2003 2014-02-27
  • 打赏
  • 举报
回复
引用 9 楼 SKATE11 的回复:
[quote=引用 5 楼 mujiok2003 的回复:] 是一个有缺陷的实现。
#include <iostream>  
#include <string>  
using namespace std;  
  
  
class Prototype  
{  
public:  
#ifdef VD
    virtual ~Prototype() {} 
#endif
    virtual Prototype *Clone() = 0;  
    virtual void display() = 0;  
};  
  
struct Resource
{
  Resource()
  {
    std::cout << "creating resource " << this << std::endl;
  }
  Resource(Resource const& )
  {
    std::cout << "creating resource " << this << std::endl;
  }
  ~Resource()
  {
    std::cout << "destroying resource " << this << std::endl;
  }
};

class Prototype2:public Prototype  
{  
protected:  
    string name;  
    Resource* pr;
public:  
    ~Prototype2()  
    {
      delete pr;
    }
    Prototype2(string name)  
    {  
        this->name = name;  
        pr = new Resource();
    }  
    Prototype2(const Prototype2&type)  
    {  
        this->name = type.name;  
        pr = new Resource(*type.pr);
    }  
  
    virtual void display()  
    {  
        cout<<"my name is : "<< this->name <<endl;  
    }  
    Prototype *Clone()  
    {  
        return new Prototype2(*this);  
    }  
};  
  
int main()  
{  
  
    Prototype *obj4 = new Prototype2("fulima");  
    Prototype *obj6 = obj4->Clone();  
  
    obj4->display();  
    obj6->display();  
      
    delete obj4;  
    delete obj6;  
  
    return 0;  
} 

c:\demo>cl /nologo /EHsc /W4 /DVD demo.cpp
demo.cpp

c:\demo>demo
creating resource 001F7F68
creating resource 001F7FC0
my name is : fulima
my name is : fulima
destroying resource 001F7F68
destroying resource 001F7FC0

c:\demo>cl /nologo /EHsc /W4  demo.cpp
demo.cpp

c:\demo>demo
creating resource 002A7F68
creating resource 002A7FC0
my name is : fulima
my name is : fulima

c:\demo>
其实我的疑问就是 用基类指针 删除派生类new出来的对象 这样是否会存在内存泄露[/quote] 你的例子没有泄露,我的例子中可能泄露了。
赵4老师 2014-02-27
  • 打赏
  • 举报
回复
检查是否资源泄漏的办法之一: 在任务管理器 进程 查看 选择列 里面选择:内存使用、虚拟内存大小、句柄数、线程数、USER对象、GDI对象 让你的程序(进程)不退出,循环执行主流程很多遍,越多越好,比如1000000次甚至无限循环,记录以上各数值,再隔至少一小时,越长越好,比如一个月,再记录以上各数值。如果以上两组数值的差较大或随时间流逝不断增加,则铁定有对应资源的资源泄漏!
menzi11 2014-02-27
  • 打赏
  • 举报
回复
引用 7 楼 FrankHB1989 的回复:
[quote=引用 6 楼 menzi11 的回复:] [quote=引用 4 楼 vipcxj 的回复:] 不会泄露,确实如LS所说,基类的析构函数最好声明为virtual,这样delete时才能调用正确的析构函数。但LZ给的例子中无论是基类还是子类都压根没写析构函数,所以不会有问题~
那个,不写析构函数的话编译器会自动给子类的默认析构函数加上virtual吗?[/quote] 不会。会造成不必要的冗余和开销。[/quote] 这么说还是泄露了......
SKATE11 2014-02-27
  • 打赏
  • 举报
回复
引用 5 楼 mujiok2003 的回复:
是一个有缺陷的实现。
#include <iostream>  
#include <string>  
using namespace std;  
  
  
class Prototype  
{  
public:  
#ifdef VD
    virtual ~Prototype() {} 
#endif
    virtual Prototype *Clone() = 0;  
    virtual void display() = 0;  
};  
  
struct Resource
{
  Resource()
  {
    std::cout << "creating resource " << this << std::endl;
  }
  Resource(Resource const& )
  {
    std::cout << "creating resource " << this << std::endl;
  }
  ~Resource()
  {
    std::cout << "destroying resource " << this << std::endl;
  }
};

class Prototype2:public Prototype  
{  
protected:  
    string name;  
    Resource* pr;
public:  
    ~Prototype2()  
    {
      delete pr;
    }
    Prototype2(string name)  
    {  
        this->name = name;  
        pr = new Resource();
    }  
    Prototype2(const Prototype2&type)  
    {  
        this->name = type.name;  
        pr = new Resource(*type.pr);
    }  
  
    virtual void display()  
    {  
        cout<<"my name is : "<< this->name <<endl;  
    }  
    Prototype *Clone()  
    {  
        return new Prototype2(*this);  
    }  
};  
  
int main()  
{  
  
    Prototype *obj4 = new Prototype2("fulima");  
    Prototype *obj6 = obj4->Clone();  
  
    obj4->display();  
    obj6->display();  
      
    delete obj4;  
    delete obj6;  
  
    return 0;  
} 

c:\demo>cl /nologo /EHsc /W4 /DVD demo.cpp
demo.cpp

c:\demo>demo
creating resource 001F7F68
creating resource 001F7FC0
my name is : fulima
my name is : fulima
destroying resource 001F7F68
destroying resource 001F7FC0

c:\demo>cl /nologo /EHsc /W4  demo.cpp
demo.cpp

c:\demo>demo
creating resource 002A7F68
creating resource 002A7FC0
my name is : fulima
my name is : fulima

c:\demo>
其实我的疑问就是 用基类指针 删除派生类new出来的对象 这样是否会存在内存泄露
mujiok2003 2014-02-27
  • 打赏
  • 举报
回复
引用 13 楼 SKATE11 的回复:
[quote=引用 12 楼 mujiok2003 的回复:] [quote=引用 9 楼 SKATE11 的回复:] [quote=引用 5 楼 mujiok2003 的回复:] 是一个有缺陷的实现。
#include <iostream>  
#include <string>  
using namespace std;  
  
  
class Prototype  
{  
public:  
#ifdef VD
    virtual ~Prototype() {} 
#endif
    virtual Prototype *Clone() = 0;  
    virtual void display() = 0;  
};  
  
struct Resource
{
  Resource()
  {
    std::cout << "creating resource " << this << std::endl;
  }
  Resource(Resource const& )
  {
    std::cout << "creating resource " << this << std::endl;
  }
  ~Resource()
  {
    std::cout << "destroying resource " << this << std::endl;
  }
};

class Prototype2:public Prototype  
{  
protected:  
    string name;  
    Resource* pr;
public:  
    ~Prototype2()  
    {
      delete pr;
    }
    Prototype2(string name)  
    {  
        this->name = name;  
        pr = new Resource();
    }  
    Prototype2(const Prototype2&type)  
    {  
        this->name = type.name;  
        pr = new Resource(*type.pr);
    }  
  
    virtual void display()  
    {  
        cout<<"my name is : "<< this->name <<endl;  
    }  
    Prototype *Clone()  
    {  
        return new Prototype2(*this);  
    }  
};  
  
int main()  
{  
  
    Prototype *obj4 = new Prototype2("fulima");  
    Prototype *obj6 = obj4->Clone();  
  
    obj4->display();  
    obj6->display();  
      
    delete obj4;  
    delete obj6;  
  
    return 0;  
} 

c:\demo>cl /nologo /EHsc /W4 /DVD demo.cpp
demo.cpp

c:\demo>demo
creating resource 001F7F68
creating resource 001F7FC0
my name is : fulima
my name is : fulima
destroying resource 001F7F68
destroying resource 001F7FC0

c:\demo>cl /nologo /EHsc /W4  demo.cpp
demo.cpp

c:\demo>demo
creating resource 002A7F68
creating resource 002A7FC0
my name is : fulima
my name is : fulima

c:\demo>
其实我的疑问就是 用基类指针 删除派生类new出来的对象 这样是否会存在内存泄露[/quote] 你的例子没有泄露,我的例子中可能泄露了。[/quote] 比如基类占的空间为8字节 派生类占的空间为12字节 那么我用基类指针指向一个派生类new出来的对象 那么在delete的时候是只释放8字节的基类部分呢还是new出来的12字节都释放掉[/quote] 在单继承时, 会完正确释放8+12=20个字节。 但是如果是多继承是, 如果没有虚析构函数, 则可能会有问题。
FrankHB1989 2014-02-27
  • 打赏
  • 举报
回复
引用 6 楼 menzi11 的回复:
[quote=引用 4 楼 vipcxj 的回复:] 不会泄露,确实如LS所说,基类的析构函数最好声明为virtual,这样delete时才能调用正确的析构函数。但LZ给的例子中无论是基类还是子类都压根没写析构函数,所以不会有问题~
那个,不写析构函数的话编译器会自动给子类的默认析构函数加上virtual吗?[/quote] 不过如果基类有写了virtual析构函数,那么和其它成员函数类似会隐式virtual。
FrankHB1989 2014-02-27
  • 打赏
  • 举报
回复
引用 6 楼 menzi11 的回复:
[quote=引用 4 楼 vipcxj 的回复:] 不会泄露,确实如LS所说,基类的析构函数最好声明为virtual,这样delete时才能调用正确的析构函数。但LZ给的例子中无论是基类还是子类都压根没写析构函数,所以不会有问题~
那个,不写析构函数的话编译器会自动给子类的默认析构函数加上virtual吗?[/quote] 不会。会造成不必要的冗余和开销。
menzi11 2014-02-27
  • 打赏
  • 举报
回复
引用 4 楼 vipcxj 的回复:
不会泄露,确实如LS所说,基类的析构函数最好声明为virtual,这样delete时才能调用正确的析构函数。但LZ给的例子中无论是基类还是子类都压根没写析构函数,所以不会有问题~
那个,不写析构函数的话编译器会自动给子类的默认析构函数加上virtual吗?
mujiok2003 2014-02-26
  • 打赏
  • 举报
回复
是一个有缺陷的实现。
#include <iostream>  
#include <string>  
using namespace std;  
  
  
class Prototype  
{  
public:  
#ifdef VD
    virtual ~Prototype() {} 
#endif
    virtual Prototype *Clone() = 0;  
    virtual void display() = 0;  
};  
  
struct Resource
{
  Resource()
  {
    std::cout << "creating resource " << this << std::endl;
  }
  Resource(Resource const& )
  {
    std::cout << "creating resource " << this << std::endl;
  }
  ~Resource()
  {
    std::cout << "destroying resource " << this << std::endl;
  }
};

class Prototype2:public Prototype  
{  
protected:  
    string name;  
    Resource* pr;
public:  
    ~Prototype2()  
    {
      delete pr;
    }
    Prototype2(string name)  
    {  
        this->name = name;  
        pr = new Resource();
    }  
    Prototype2(const Prototype2&type)  
    {  
        this->name = type.name;  
        pr = new Resource(*type.pr);
    }  
  
    virtual void display()  
    {  
        cout<<"my name is : "<< this->name <<endl;  
    }  
    Prototype *Clone()  
    {  
        return new Prototype2(*this);  
    }  
};  
  
int main()  
{  
  
    Prototype *obj4 = new Prototype2("fulima");  
    Prototype *obj6 = obj4->Clone();  
  
    obj4->display();  
    obj6->display();  
      
    delete obj4;  
    delete obj6;  
  
    return 0;  
} 

c:\demo>cl /nologo /EHsc /W4 /DVD demo.cpp
demo.cpp

c:\demo>demo
creating resource 001F7F68
creating resource 001F7FC0
my name is : fulima
my name is : fulima
destroying resource 001F7F68
destroying resource 001F7FC0

c:\demo>cl /nologo /EHsc /W4  demo.cpp
demo.cpp

c:\demo>demo
creating resource 002A7F68
creating resource 002A7FC0
my name is : fulima
my name is : fulima

c:\demo>
vipcxj 2014-02-26
  • 打赏
  • 举报
回复
不会泄露,确实如LS所说,基类的析构函数最好声明为virtual,这样delete时才能调用正确的析构函数。但LZ给的例子中无论是基类还是子类都压根没写析构函数,所以不会有问题~
「已注销」 2014-02-26
  • 打赏
  • 举报
回复
楼主选择下代码格式,更于复制调试
menzi11 2014-02-26
  • 打赏
  • 举报
回复
引用 1 楼 menzi11 的回复:
不会泄露,这样的代码很常见
抱歉,我还以为楼主是问clone函数呢,clone不会泄露,但是由于析构函数没有设为virtual, 所以当父类指针delete的时候调用的是父类的析构函数,所以会泄露
menzi11 2014-02-26
  • 打赏
  • 举报
回复
不会泄露,这样的代码很常见

64,639

社区成员

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

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