c++ - 为什么从构造函数抛出异常时会发生内存泄漏?

标签 c++ c++11 exception memory-leaks

我阅读了 Paul DeitelC++ How to Program 8th Edition 一书。在第 645 页有一个声明:

When an exception is thrown from the constructor for an object that's created in a new expression, the dynamically allocated memory for that object is released.

为了验证这个说法,我写了如下代码:

#include <iostream>
#include <exception>
#include <memory>

class A{
public:
  A(){std::cout << "A is coming." << std::endl;}
  ~A(){std::cout << "A is leaving." << std::endl;}
};
class B
{
public:
  B()
  {
    std::cout << "B is coming." << std::endl;
    A b;
    throw 3;
  }
  ~B(){std::cout << "B is leaving." << std::endl;}
};

int main(void)
{
    try
    {
        std::shared_ptr<B> pi(new B);
    }
    catch(...)
    {
      std::cout << "Exception handled!" << std::endl;
    }
}

输出是:

B is coming.
A is coming.
A is leaving.
Exception handled!

这表明没有调用B的析构函数,这似乎与上面的说法冲突。

我的代码是否正确以验证声明?如果不是,我应该如何修改它?如果是,是否说明这个说法是错误的?

最佳答案

你混淆了两件事:

  • 正在释放内存
  • 被调用的析构函数

您已经证明后者不会发生,这是有道理的:您如何才能摧毁未正确构建的东西?请注意,成员变量调用它们的析构函数,因为在构造函数抛出异常时所有成员变量都已完全构造。

但这与释放内存无关,肯定会发生。

[C++11: 15.2/2]: An object of any storage duration whose initialization or destruction is terminated by an exception will have destructors executed for all of its fully constructed subobjects (excluding the variant members of a union-like class), that is, for subobjects for which the principal constructor (12.6.2) has completed execution and the destructor has not yet begun execution. Similarly, if the non-delegating constructor for an object has completed execution and a delegating constructor for that object exits with an exception, the object’s destructor will be invoked. If the object was allocated in a new-expression, the matching deallocation function (3.7.4.2, 5.3.4, 12.5), if any, is called to free the storage occupied by the object.

关于c++ - 为什么从构造函数抛出异常时会发生内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30821651/

相关文章:

c++ self 在初始化列表中

c++ - 来自可变模板的模棱两可的成员请求

c++ - 模板方法 enable_if 特化

Java 自定义异常处理

Java 索引越界异常

android - 在捕获异常时在 Android 中显示自定义 AlertDialog

c++ - C++ 的英语语法检查器库

c++ - 防止从 bool 到 char 的隐式转换

c++ - 如何在场景中找到一个项目

具有一个或多个空格的 C++11 正则表达式