Chinaunix首页 | 论坛 | 博客
  • 博客访问: 183326
  • 博文数量: 38
  • 博客积分: 2010
  • 博客等级: 大尉
  • 技术积分: 372
  • 用 户 组: 普通用户
  • 注册时间: 2008-01-05 19:39
文章分类

全部博文(38)

文章存档

2011年(1)

2010年(2)

2009年(2)

2008年(33)

我的朋友

分类: C/C++

2008-08-22 13:44:31

在《Thinking in C++》Vol 2(Page 12.cn)中提出,当对象在构造函数中抛出异常时,析构函数无法调用,因为对象没有构造完成。那么先前分配的内存将不能回收。而《Exceptional C++》(Page 25.cn)上面却说,“第二个操作是T的默认构造函数,在这个函数中可能抛出任意的异常,在失败的情况下,所有已构造的T对象都会被销毁”(Second, T's default constructor, which might throw anything at all, in which case any objects that were constructed are destroyed and the allocated memory is automatically guaranteed to be deallocated via operator delete[]().)

其实,他们说的都是对的。假如,某个类包含两种对象,Cat和Dog两个对象,Cat先构造而Dog后构造,在Dog抛出异常后,Dog已构造好的对象就会被析构,而先前构造的Cat对象不会析构,那么就会造成内存泄露。

// 这是Herb Sutter的Stack的够造函数

template<class T>
Stack<T>::Stack()
: v_(0),
vsize_(10),
vused_(0) // nothing used yet

{
  v_ = new T[vsize_]; // initial allocation
}

//这是我根据Bruce的例子改的一个程序
#include <iostream>

using namespace std;

static unsigned num = 0;

class Cat
{
public:
    Cat() { cout << "Cat()" << endl; }
    ~Cat() { cout << "~Cat()" << endl; }
};

class Dog
{
public:
    Dog()
    {
        cout <<"Allocating the " << num+1 << " Dog()"<<endl;
        ++num;
        if(num == 4)
            throw 23;
    }
    ~Dog()
    {
        --num;
        cout << "Delete the " << num << " ~Dog()" <<endl;
    }
};

class UseResource
{
private:
    Cat *bp;
    Dog *op;
public:
    UseResource(int count=1):bp(new Cat[count]),op(new Dog[count])
    {
        cout << "UseResource()" << endl;
// bp = new Cat[count];
// op = new Dog[count];
    }
    ~UseResource()
    {
        cout << "~UseResource()"<<endl;
        delete []bp;
        delete []op;
    }
};

int main()
{
    try
    {
        UseResource ur(4);
    }
    catch(int)
    {
        cout << "inside handler" <<endl;
    }
}

其输出为
C:\WINDOWS\system32\cmd.exe /c a.exe
Cat()
Cat()
Cat()
Cat()
Allocating the 1 Dog()
Allocating the 2 Dog()
Allocating the 3 Dog()
Allocating the 4 Dog()
Delete the 3 ~Dog()
Delete the 2 ~Dog()
Delete the 1 ~Dog()
inside handler
Hit any key to close this window...

由此可以看出,第四个Dog的构造并未完成(这和我代码的结构也有关系),但是前面三个构造好的Dog都被析构了,而Cat并未析构,这样就会内存泄露了,咋办?
可以,嗯……
使用 shared_ptr<Cat> bp;
或者自己构造句柄(参见《C++沉思录》),算了还是使用别人弄好的吧!

阅读(1006) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~