为什么shared_ptr在发生异常时不会调用指针的析构函数

时间:2015-03-21 11:14:46

标签: c++11 shared-ptr

我测试了C ++ 11 shared_ptr,并感到惊讶 在这个例子中

#include <iostream>
#include <vector>
#include <memory>
#include <string>
#include <exception>

using namespace std;

class MyExc
{

};

class Slot
{
public:
    Slot(const std::string &str = "NONAME") : m_name(str)
    {
        cout << "Constructor of slot: " << m_name << endl;
    }

    virtual ~Slot()
    {
        cout << "Destructor of slot: " << m_name << endl;
    }

    void sayName()
    {
        cout << "Slot name is: " << m_name << endl;
//       throw MyExc();
    }

private:
    string m_name;
};


void testShared(shared_ptr<Slot> & m_share)
{
    m_share->sayName();
}

int main()
{
    vector<shared_ptr<Slot>> vec {make_shared<Slot>("0"), make_shared<Slot>("1"), make_shared<Slot>("2"), make_shared<Slot>("3"), make_shared<Slot>("4")};
    for (auto& x:vec)
        testShared(x);


    return 0;
}

我看到了正确的输出

插槽构造函数:0
插槽构造:1
插槽构造:2
插槽构造:3
插槽构造:4
插槽名称为:0
插槽名称是:1
插槽名称是:2
插槽名称是:3
插槽名称是:4
槽的析构函数:0
槽的析构函数:1
槽的析构函数:2
槽的析构函数:3
插槽的析构函数:4

但如果我取消注释行

throw MyExc();

输出已更改,析构函数调用消息未显示

在抛出&#39; MyExc&#39;的实例后终止调用 插槽构造:0
插槽构造:1
插槽构造:2
插槽构造:3
插槽构造:4
插槽名称为:0

这是否意味着内存泄漏?

1 个答案:

答案 0 :(得分:1)

在你的情况下,是的,有一个内存泄漏(不是很重要,因为程序将立即终止,操作系统将回收内存)。

为了实现这一点,您需要注意堆栈展开(即,在调用堆栈时销毁局部变量)仅由标准保证,如果异常被捕获。如果异常永远不会被捕获并直接进入std::terminate,无论是否发生展开都取决于编译器和&amp;标准库。

引用C ++ 11:

15.2:

  

1当控件从 throw-expression 传递给处理程序时,将为所有自动对象调用析构函数   从输入try块开始构造。自动对象以相反的顺序销毁   完成他们的建设。

     

3为从try块到a的路径构造的自动对象调用析构函数的过程    throw-expression 被称为“堆栈展开。” ...

15.3:

  

9如果未找到匹配的处理程序,则调用函数std::terminate();是否堆栈   在对std::terminate()的调用之前解开是实现定义的(15.5.1)。