离开 c++ 应用程序而不运行全局静态对象的析构函数

Leaving a c++ application without running destructors of global static objects

本文关键字:静态 对象 析构函数 全局 运行 c++ 应用程序 离开      更新时间:2023-10-16

我"继承"了一个设计,在该设计中,我们使用一些全局对象在应用程序退出时执行操作(更新应用程序状态日志文件等...对问题不重要)。

基本上,应用程序

创建特定类的虚拟帮助程序对象,并让它们的析构函数在应用程序正常退出或遇到错误时执行这些额外的工作(并且应用程序知道在所有情况下该怎么做,同样与问题无关)。

但是现在我遇到了一种情况,我不想调用这些析构函数,只是离开应用程序而不执行这些"终止作业"。我怎样才能以一种体面的、独立于平台的方式做到这一点?我不想要零除法之类的解决方案:)

编辑:我知道设计坏了:)我们正在努力修复它。

编辑2:我想避免任何异常退出的"痕迹"......抱歉,规格晚了。

Edit3:获取对析构函数源代码的访问权限以修改它们非常困难。当政客们接管键盘并试图编写程序时,就会发生这种情况。我们只知道,"他们的"析构函数将在退出时运行......

我怎样才能以一种体面的、独立于平台的方式做到这一点?

你不能。 至少不是以一种体面的方式。

您可以通过throw异常而不是catch异常来实现此目的。 最终结果将是您的应用程序将非常不优雅地终止。 不会调用析构函数。 这是相当丑陋的,非常黑客的。 如果你的设计依赖于这种行为来正确运行,那么你的设计不仅完全疯狂,而且几乎不可能维护。

我更喜欢在您不想为其运行析构函数的对象中设置布尔标志。 如果设置了此标志,则不会运行销毁代码。 析构函数仍将触发,但可以跳过要避免运行的实际代码。


如果控制全局的构造,则可以利用运算符placement-new 。 构建一个足够大的全局char缓冲区,然后在那里placement-new全局。 由于以这种方式构造的对象必须通过显式调用析构函数来销毁,因此不要在全局关闭时调用析构函数。

abort();

中止当前进程,导致程序异常终止。

该函数会提高SIGABRT信号(好像提高(SIGABRT)是 叫)。如果未捕获,则会导致程序终止返回 主机的与平台相关的不成功终止错误代码 环境。

程序终止时不会破坏任何对象,也不会 调用传递给 atexit 或 at_quick_exit 的任何函数。

接受您对"我们知道它已损坏"的评论...

在某个地方放一个全局布尔值

bool isExiting;

退出时将其设置为 true。

在你的析构函数中做

if( !global::isExiting )
{
   // destruction code here
}

躲在某个地方,彻底羞愧。

最简单的方法是将全局对象替换为堆分配的指向对象的指针。这样,为了运行它们的析构函数,您必须手动delete它们。请注意,这当然非常非常令人讨厌。比使用原始指针更好的方法是使用std::unique_ptr,如果不应调用析构函数,则release它。

如果您不想更改与全局对象交互的客户端代码(并且需要非指针类型),只需将实际指针包装到全局代理对象中即可。

(PS:这种设计很少,但非常合理。有时不调用析构函数是完全安全的,调用它们可能是有害的,例如,因为众所周知它们只释放内存,但由于许多嵌套析构函数调用,它们需要很长时间。这仍然需要非常小心地完成,但根本不是"糟糕的设计"。

它很丑陋,但它有效:

  1. 创建简单的制作者类。

  2. Maker 的构造函数应该分配你喜欢的对象,并将其分配给静态指针。

  3. 确保在制造商的析构函数中不执行任何操作。

  4. 创建制作者的单个静态实例。

  5. 为了使事情看起来更好,请将静态指针设为私有并写入内联访问器函数,该函数会将您拥有的静态指针转换为公共引用。