【问题标题】:Smart pointer not able to deallocate memory [duplicate]智能指针无法释放内存[重复]
【发布时间】:2013-06-01 08:35:10
【问题描述】:

我的智能指针实现如下所示,它不会在异常时释放内存..

template <class T>
class SMARTPOINTER
{
public:
   SMARTPOINTER(T* pointee) : SMART_POINTEE(pointee) {
    cout <<"\n Inside class SMARTPOINTER CONSTURCTOR \n";
   }

   ~SMARTPOINTER() {
     cout <<"\n Inside class SMARTPOINTER DESTRUCTOR \n";
      delete SMART_POINTEE;
   }

   T& operator*() const
   {
      cout <<"\n Inside class SMARTPOINTER operator* \n";
      return *SMART_POINTEE;
   }

   T* operator->() const
   {
      cout <<"\n Inside class SMARTPOINTER operator->()  \n";
      return SMART_POINTEE;
   }

private:
   T* SMART_POINTEE;

};

class Widget
{
public:

  Widget() {
      cout <<"\n Inside Widget CONSTRUCTOR \n";
  }

   void Fun() { 
     cout <<"\n Inside Widget::Fun() \n";
   }

  ~Widget() {
      cout <<"\n Inside Widget DESTRUCTOR \n";
  }

};

class THROWME{

};

int main() {

SMARTPOINTER<Widget> sp(new Widget);
sp->Fun();
throw new THROWME;
(*sp).Fun();

return 0 ;
}

我发现输出是

Inside Widget CONSTRUCTOR 

 Inside class SMARTPOINTER CONSTURCTOR 

 Inside class SMARTPOINTER operator->()  

 Inside Widget::Fun() 
uncaught exception of type THROWME*
Aborted.

据我所知,智能指针应该在这种情况下帮助我!!我没有发现通过智能指针调用 Widget 的破坏。

所以我必须在这里遗漏一些实现。

阅读评论后编辑

通过 try catch 我得到了我的结果。但我仍然不知道它是否正确 修改代码

  int main() {
        try {
        SMARTPOINTER<Widget> sp(new Widget);
        sp->Fun();
        THROWME tm;
        throw tm;
        (*sp).Fun();
        }
        catch(...) {
          cout <<"\n **SOME EXCEPTION CAUGHT**  \n";
        }
        return 0 ;
        }

结果

 Inside Widget CONSTRUCTOR 

 Inside class SMARTPOINTER CONSTURCTOR 

 Inside class SMARTPOINTER operator->()  

 Inside Widget::Fun() 

 Inside class SMARTPOINTER DESTRUCTOR 

 Inside Widget DESTRUCTOR 

 **SOME EXCEPTION CAUGHT**

【问题讨论】:

  • 我不是 100%,但我认为您需要捕获异常才能调用析构函数。既然你不这样做,它就不会发生,因为“我们找不到返回的地方”错误处理程序首先启动。
  • 如果我必须捕获异常并处理东西..我宁愿不使用智能指针..我认为还有其他东西丢失..
  • 你不应该将异常作为指针抛出(你在哪里delete他们?)。就做throw THROWME();
  • @MAG:你可以不同意所有你喜欢的,但是直到 C++ 规范发生变化,你不需要 try/catch 块来知道回到哪里,运行时仍然会这样做。
  • @Joe:同意。但是最初的海报问“好吧,如果我必须到处尝试/捕捉来调用析构函数” - 对我来说,OP 似乎想要调用析构函数。与往常一样,存在“忽略错误并退出”的可能性——这在我的大部分代码中都非常有效;)

标签: c++ pointers memory smart-pointers


【解决方案1】:

没有调用析构函数,因为未处理的异常THROWME 导致调用std::terminate。另请参阅this question,特别是已接受答案中的第一个引号:

C++11 15.2 构造函数和析构函数[except.ctor]

1 当控制从 throw 表达式传递到处理程序时,将调用自 try 块 进入后构造的所有自动对象的析构函数。自动对象按照其构建完成的相反顺序被销毁。

由于没有处理异常的 try 块,因此不调用析构函数。

【讨论】:

    【解决方案2】:

    析构函数的调用是堆栈展开的一部分,当异常“冒泡”调用堆栈时完成... except当异常未处理时。那样的话,栈是否展开is implementation-defined

    如果在程序中找不到匹配的处理程序,则调用函数terminate() (except.terminate)。在调用 terminate() 之前是否展开堆栈是实现定义的。

    为了更优雅地处理这个问题,您可以使用函数 try 块:

    int main()
    try {
      // main body
    } catch (...) {
      std::cerr << "Unhandled exception\n";
      std::terminate();
    }
    

    ...虽然这会吞下异常并使其难以调试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多