gpt4 book ai didi

C++,静态对象的构造函数中的异常绕过先前静态对象的析构函数

转载 作者:行者123 更新时间:2023-11-27 22:49:35 26 4
gpt4 key购买 nike

我正在研究如何添加 C++ 异常处理来处理现有实时应用程序中的运行时错误。我从为硬件系统组件封装驱动程序的对象构造失败开始,例如位于 Raspberry Pi 平台的 SPI 总线上的电源监控器微 Controller 。

遵循 RAII 原则,我必须在它们的构造函数中完全初始化这些对象,如果系统资源不可用,例如如果 SPI 驱动程序未加载,这将导致失败的可能性。由于构造函数没有返回值,我必须使用异常来处理此类失败。

这些硬件驱动对象是静态的(文件范围)。为什么?这样它们的构造函数就会自动调用,更重要的是,它们的析构函数会在程序退出时自动调用。此外,我需要从主程序文件中的任何位置获取对象,因为它们代表全局硬件资源。

我真的不关心异常是如何处理的(我可以在抛出之前发出有用的错误信息)但我关心程序是否正确终止。

发生的事情是,如果静态分配对象的构造函数失败并抛出异常,则不会调用词法上位于失败对象之前的其他静态对象的析构函数。我已经在最小的测试台上对此进行了测试。 Apple、Pear 和 Orange 类只有向标准输出声明自己的构造函数和析构函数,除了 Orange 的构造函数然后抛出异常。在主文件中,我按顺序定义了 Apple、Pear 和 Orange 的一个静态实例。构造函数在程序执行时被调用,Orange 抛出异常,程序结束时没有调用 Apple 和 Pear 的析构函数。

我在这里错过了什么?

在类似问题的答案中,例如556655,人们建议: - 不在构造函数中抛出异常。嗯? - 有一个单独的初始化方法,在构造后称为“手动”,以执行任何可能失败的操作。那么RAII呢? (顺便说一句,这就是我现在拥有的东西,没有异常(exception))。 - 将静态对象更改为指针并使用 new 运算符“手动”调用构造函数。然后我必须设法在发生故障时调用正确的析构函数,我希望使用异常可以避免这种情况。 - 将每个静态对象包装在另一个对象中,该对象具有访问器函数以获取对它的引用。显然,直到第一次在外部对象上调用访问器时,才会调用内部对象的构造函数,这将使我能够捕获异常,并且据推测,这将导致整洁的退出。这看起来像是一场可怕的混战。

回想一下,我不需要捕获异常,程序可以随心所欲地终止。这使我的问题与我发现的其他问题不同。我的问题是,为什么不为已成功构造的静态对象调用析构函数?

格雷厄姆。

最佳答案

您没有注意到未处理异常。当程序由于未处理的异常而终止时,您不能保证调用本地和静态对象的析构函数(我记得它是实现定义的)。一种解决方案是将这些对象放在一个通用的包装器对象中,在 maintry block 中创建它,然后只为所有任意访问提供一个指向它的指针也许是当前的全局变量。

素描:

class Drivers
{
friend auto main() -> int;
// ...
};

namespace impl {
Drivers* p_drivers;
} // namespace impl

auto drivers() -> Drivers& { return *impl::p_drivers; }

auto main()
-> int
{
try
{
Drivers drivers;
impl::p_drivers = &drivers;
// ...
return EXIT_SUCCESS;
}
catch( exception const& x )
{
log_failure( x.what() );
}
return EXIT_FAILURE;
}

关于C++,静态对象的构造函数中的异常绕过先前静态对象的析构函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38805643/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com