libstdc ++和Libc ++之间的Unique_ptr差异使您的应用程序崩溃

2021-02-21 07:45:05

感谢KDE FreeBSD CI,它在libc ++之上运行我们的代码,我们发现libstdc ++和libc ++的unique_ptr实现之间存在有趣的区别。这是完全出乎意料的,并且用户的实际结果甚至更出乎意料:在特定情况下可能导致崩溃。当小部件(使用d指针作为其d指针,这是当今的惯例)安装事件过滤器时,就会发生这种情况。该事件过滤器将在子窗口小部件销毁期间触发(至少对于QEvent :: Destroy事件,例如,我也曾通过QEvent :: Leave事件看到它)。并且,根据事件过滤器的编写方式,可能在检查事件类型之前使用小部件的d指针。那就是有趣的地方:unique_ptr的libc ++实现*在调用析构函数之前将其设置为null(因为它是根据reset(nullptr);实现的。但是在libstdc ++中,unique_ptr' s析构函数仅调用析构函数,其值在破坏期间仍然有效。

这是从KIO代码中提取的崩溃的测试用例,您可以在此处查看修复程序。它与gcc / libstdc ++一起使用,并与clang / libc ++一起崩溃,因为MyWindow :: eventFilter()使用的是已经为null的d指针。在这种特殊情况下,修复很容易,首先测试事件类型。无论如何,出于性能原因,这是一个好的做法。但是在其他情况下,情况有些不同,解决方案是在破坏时删除事件过滤器。