新操作员的异常安全



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

_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;
}

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

Upd:感谢评论员——实际上我指的是新表达的异常安全。

你的问题混在一起了"新表达式";以及";操作员新";。

新表达式如下:A* a = new A();C++语言定义,这个表达式的求值方式如下(在简化的伪代码上(:

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

正如您所看到的,如果发生异常,内存将被释放。

更详细的解释:

如果初始化因抛出异常而终止(例如,从构造函数(,如果新表达式分配了任何存储,则它调用适当的解除分配函数:非数组类型的运算符删除,数组类型的运算符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>

最新更新