新操作员的异常安全

这是libstdc++ 中 new 运算符的实现:

_GLIBCXX_WEAK_DEFINITION void *
operator new (std::size_t sz) _GLIBCXX_THROW (std::bad_alloc)
{
  void *p;

  /* malloc (0) is unpredictable; avoid it.  */
  if (__builtin_expect (sz == 0, false))
    sz = 1;

  while ((p = malloc (sz)) == 0)
    {
      new_handler handler = std::get_new_handler ();
      if (! handler)
        _GLIBCXX_THROW_OR_ABORT(bad_alloc());
      handler ();
    }

  return p;
}

谁保证构造函数中的异常会释放分配的内存?

更新:感谢评论员 - 实际上我的意思是新表达式的异常安全。

回答

您正在混合您的问题“新表达式”和“新运算符”。

新表达式是这样的:A* a = new A();
C++ 语言定义,这个表达式被评估为这样的东西(过度简化的伪代码):

void* __a = operator new(sizeof(A));
try {
   A::A(this = static_cast<A*>(__a));
} catch (...) {  operator delete (__a); throw; }

如您所见 - 如果发生异常,内存将被解除分配。

更详细的解释:

如果初始化因抛出异常(例如来自构造函数)而终止,如果 new 表达式分配了任何存储空间,它将调用适当的释放函数:对于非数组类型的 operator delete,对于数组类型的 operator delete[]。


对于编译器真正生成的代码 - 请参阅此处。您可能会注意到对 operator delete 的调用 - 即使源代码不包含它:

struct A { A(); };
A::A() { throw 13; }

int main()
{
    auto a = new A();
}

汇编器:

 call 401040 <operator new(unsigned long)@plt>
...
 call 401172 <A::A()>
...
 call 401050 <operator delete(void*, unsigned long)@plt>
...
 call 401080 <_Unwind_Resume@plt>

  • It is generated by the compiler

以上是新操作员的异常安全的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>