2016-06-13 78 views
2

,我读了智能指针有帮助的情况下,当构造产生一些例外。智能指针和构造异常

的问题是,构造有例外发生之前的一些资源,但析构函数不叫(和资源永久繁忙)。

但我不能正确它已了解。 我的代码:

#include <memory> 
#include <iostream> 

class resOwner { 
    public: 
    resOwner() { 
     std::cout << "Map some huge resources\n"; 
     throw "hi"; 
    } 

    ~resOwner() { 
     std::cout << "Free some huge resources\n"; 
    } 
}; 

class normal : resOwner { 
}; 

int main(){ 
    try { 
     std::shared_ptr<resOwner> k (new resOwner()); 
    } catch (...) {} 
} 

输出为Map some huge resources。 如何用智能指针解决资源泄漏问题?

+1

别担心 - 不从智能指针合作 - - 如果C-TOR抛出内存被释放,看到http://stackoverflow.com/questions/1674980/who-deletes-the-在 – PiotrNycz

+0

中,无论resOwner拥有的资源必须是某种智能指针unique_ptr或shared_ptr等,否则最终会导致资源泄漏因为无论你计划在析构函数中清理什么都不会被调用。 – Arunmu

+1

值得指出的是,如果一个构造函数运行到完成(构造函数委托)并且委托构造函数抛出,那么该对象的析构函数将被调用。 – Blazo

回答

4

如何解决与智能指针这个资源泄漏?

裹在一个RAII容器中的资源,并存储作为容器的resOwner成员。你不一定需要智能指针。

struct resource { 
    resource() { 
     std::cout << "Map some huge resources\n"; 
    } 
    ~resource() { 
     std::cout << "Free some huge resources\n"; 
    } 
}; 

struct resOwner { 
    resource res; 
    resOwner() { 
     throw "hi"; 
    } 
}; 

如果这巨大的资源是动态分配的对象,那么你就需要实现一个单独的resource类,因为标准库已经具备了这些容器:std::unique_ptr。如果它是一个动态分配的阵列,那么你可以使用std::vector

其工作原理:当构造函数体或子对象的构造函数之一抛出,所有子对象已经构建(成员和基本对象),将被销毁。这保证将会调用~resource

3

你应该使用智能指针的资源,他们会帮助你避免资源泄漏。如:

class resource { 
public: 
    resource() { 
     std::cout << "resource allocated\n"; 
    } 
    ~resource() { 
     std::cout << "resource deallocated\n"; 
    } 
}; 

class resOwner { 
    std::shared_ptr<resource> res; 
public: 
    resOwner() : res(new resource) { 
     std::cout << "Map some huge resources\n"; 
     throw "hi"; 
     // res will be destroyed even though exception happened 
    } 
    ~resOwner() { 
     // nothing need to do here 
    } 
}; 

LIVE

1

实际上创建对象之前,抛出异常。由于没有创建对象,因此不会调用其析构函数。另一方面,如果在构造函数中引发了一个异常,那么对于构造函数完成执行的所有子对象,析构函数将被调用。试试这个比较:

class Resource 
{ 
public: 
    Resource() 
    { 
     std::cout << "constructing resource" << std::endl; 
    } 
    ~Resource() 
    { 
     std::cout << "destroying resource" << std::endl; 
    } 
}; 

class Owner 
{ 
    ::std::unique_ptr <Resource> theResource; 
public: 
    Owner() 
      : theResource(new Resource()) 
    { 
     std::cout << "Map some huge resources\n"; 
     throw "hi"; 
    } 

    ~Owner() 
    { 
     std::cout << "Free some huge resources\n"; 
    } 
};