c++ - 当新表达式的参数子表达式抛出时释放内存

标签 c++ visual-c++ memory-leaks exception-handling language-lawyer

动态分析在我们的代码库中发现了奇怪的内存泄漏。有问题的代码如下所示:

Something *p = new Something(getArgument());

函数 getArgument() 有时会抛出异常。当它抛出时,新分配的对象被泄露。这是由 Visual Studio 2015 (MSC++ 19.0) 编译的。

现在,当我检查规范 ( C++14 final draft ) 时,§5.3.4/8 奇怪地说:

A new-expression may obtain storage for the object by calling an allocation function (3.7.4.1). If the new-expression terminates by throwing an exception, it may release storage by calling a deallocation function (3.7.4.2). If the allocated type is a non-array type, the allocation function’s name is operator new and the deallocation function’s name is operator delete. If the allocated type is an array type, the allocation function’s name is operator new[] and the deallocation function’s name is operator delete[].

此处使用“可能”(由我在上面突出显示)意味着编译器可以自由选择不这样做。

这是这样的:

  1. 在规范的其他地方按要求声明,使其成为 Visual C++ 编译器中的错误(可能只在某些情况下发生;没有检查它的普遍性),
  2. 规范中的错误,或者
  3. 出于某种原因这样写?

注意:当表达式完成时,代码会正确删除对象。那没有错误。问题严格在于 new 表达式抛出时会发生什么。

最佳答案

来自最新的草稿,相关引述在:

expr.new/8: A new-expression may obtain storage for the object by calling an allocation function ([basic.stc.dynamic.allocation]). If the new-expression terminates by throwing an exception, it may release storage by calling a deallocation function. ....

“可能”的使用优先于进行中的部分:

expr.new/21 If any part of the object initialization described above terminates by throwing an exception and a suitable deallocation function can be found, the deallocation function is called to free the memory in which the object was being constructed, after which the exception continues to propagate in the context of the new-expression. If no unambiguous matching deallocation function can be found, propagating the exception does not cause the object's memory to be freed. [ Note: This is appropriate when the called allocation function does not allocate memory; otherwise, it is likely to result in a memory leak. — end note  ]


但在 C++14 及更早的版本中,新表达式的不确定顺序让您大吃一惊;其中说:

$5.3.4/18 The invocation of the allocation function is indeterminately sequenced with respect to the evaluations of expressions in the new-initializer. Initialization of the allocated object is sequenced before the value computation of the new-expression. It is unspecified whether expressions in the new-initializer are evaluated if the allocation function returns the null pointer or exits using an exception.

摘自 C++14 草案

根据 this paper 的采用.我们现在在 C++17 中定义了一个序列:

expr.new/19 The invocation of the allocation function is sequenced before the evaluations of expressions in the new-initializer. Initialization of the allocated object is sequenced before the value computation of the new-expression.



关于c++ - 当新表达式的参数子表达式抛出时释放内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43915004/

相关文章:

c++ - *实时*访问光盘文件中的数据

python - Cython 扩展类 : How do I expose methods in the auto-generated C struct?

c++ - 如何使用指针函数写入/读取数组

c++ - 如何使用/创建 boost::multi_index?

c++ - 模板特化静态初始化 icc+vc vs gcc+clang

c++ - 如何确保自己编写 C++ 代码时不会导致任何内存泄漏?

Python C API : Assigning PyObjects to a dictionary causes memory leak

c++ - extern"C"与 extern 的区别

c++ - g++ -static 导致内存泄漏(mtrace 报告)

windows - 将 hwnd GDI 调用重定向到系统内存位图?