智能指针无法释放内存

Smart pointer not able to deallocate memory

本文关键字:释放 内存 指针 智能      更新时间:2023-10-16

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

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.

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

所以我在这里一定遗漏了一些实现。

与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**

析构函数没有被调用,因为未处理的异常THROWME导致std::terminate被调用。参见这个问题,特别是被接受的答案中的第一个引语:

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

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

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

析构函数的调用是堆栈展开的一部分,这是在异常"冒泡"调用堆栈时完成的…除非异常未处理。在这种情况下,是否展开堆栈是由实现定义的:

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

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

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

…尽管这将吞噬异常并使调试变得困难。