【问题标题】:Smart pointer destructors under exceptional circumstances特殊情况下的智能指针析构函数
【发布时间】:2018-12-12 06:10:58
【问题描述】:

在阅读 C++ 中的智能指针时,大部分信息都带有一个警告:

"请注意,将(可能)不会调用智能指针析构函数 异常退出等情况(通过调用 std::abort 或 std::exit()),或者当异常从线程的 主函数或当声明为 noexcept 的方法抛出 例外”。

我的问题是,在所有这些情况下,程序最终都会终止,在这种情况下,当进程的页表被清除时,操作系统会收回智能指针指向的内存(我知道 C++ 标准没有讨论页表和虚拟内存,但我在这里提到它是因为这是大多数操作系统的标准做法。

那么为什么会发出这个警告呢?如果不调用析构函数,可能发生的最糟糕的事情是什么?或者这是我在使用智能指针管理内存以外的资源时需要注意的警告?如果是,那么这些资源是什么?

【问题讨论】:

  • 指向对象的析构函数可能会同步和关闭外部资源,如串行线、文件、套接字,甚至可能设置一些 GPIO。所以对于智能指针来说,它主要是关于释放内存,但对于它持有更多的对象可能是相关的。
  • 设计一个析构函数,它提交了部分文件数据,其余部分位于队列中,然后拔掉插头。您的猜测与我的猜测一样好,最终将其写入文件。通过套接字发送数据,然后在中途终止连接。可能受到影响的事物的清单是无限的,只留给想象。而且,同样的问题可能会发生没有智能指针,尤其是std::abort。所以我觉得这个警告唯一奇怪的是它对智能指针的亲和力。
  • 所以当我使用智能指针来管理这些时,不能保证这些会被关闭。那么程序员应该怎么做,因为我上面提到的情况会导致程序无论如何都会终止并且它已经超出了你的控制范围。
  • @AshishDaggubatti,当程序/线程像这样终止时,您将无能为力。该标准只是正确设置了程序的期望。
  • @AshishDaggubatti 你问程序员能做什么?防止上述情况发生。在main 中捕获异常。不要抛出声明为noexcept 的函数。并且不要调用abortexit,让所有被调用的函数都返回并在main 中执行return

标签: c++ c++11 c++14 smart-pointers


【解决方案1】:

正如我在我的 cmets 中已经说过的,标准所讨论的情况是不应该发生的特殊情况。如果发生这种情况,您的程序将无法正常运行的可能性非常高。所以它被终止了,标准不保证所有的析构函数都被正确调用。

解决办法是防止这种情况发生。

异常退出(通过调用 std::abort 或 std::exit())

请勿致电abortexit。让所有被调用的函数返回并让main 执行return

或者当异常从线程的主函数传播出去时

捕获main 中的所有异常。然后return。或者如果没有全局对象也可以abort

或者当声明为 noexcept 的方法抛出异常时”。

不要加入 noexcept 函数。

可能出现的问题不仅与内存有关。删除它持有的指针的智能指针会触发它指向的对象的析构函数。该对象可能拥有外部资源。例如,这些可能是一个文件(或套接字),在关闭之前应该刷新(写出缓冲的 I/O)。它也可能是一些低级硬件相关的东西,例如 GPIO,例如在操作期间打开灯并在析构函数中将其关闭。

【讨论】:

    猜你喜欢
    • 2012-04-17
    • 2011-04-06
    • 2018-02-02
    • 2016-03-20
    • 2019-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多