- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
以下示例使用 Linux 上的 gcc 11 (GNU STL) 和 FreeBSD 上的 clang 12 (Clang STL) 进行编译。在 Linux 上,它运行并打印值 1 和 2。在 FreeBSD 上,它打印值 1,然后因 SEGV 崩溃。我不太了解对象的生命周期——所以整个事情可能是 UB 并且运行时行为可能不相关。我确实知道 std::unique_ptr
的实现这两个 STL 之间有一个重要的区别:Clang STL 重置 std::unique_ptr
的内部指针至nullptr
在析构函数的开始处,而 GNU STL 则单独保留指针。
#include <iostream>
#include <memory>
struct C {
struct Private {
C* m_owner;
int m_x;
Private(C* owner) : m_owner(owner), m_x(0) {}
~Private() { m_owner->cleanup(); }
void cleanup() { std::cout << "Private x=" << ++m_x << '\n'; }
};
std::unique_ptr<Private> d;
C() { d = std::make_unique<Private>(this); }
~C() = default;
void cleanup() { d->cleanup(); }
};
int main(int argc, char **argv)
{
C c;
c.cleanup(); // For display purposes, print 1
return 0; // Destructors called, print 2
}
FreeBSD 上的输出:
Private x=1
Segmentation fault (core dumped)
和一段回溯:
* thread #1, name = 'a.out', stop reason = signal SIGSEGV: invalid address (fault address: 0x8)
frame #0: 0x00000000002032b4 a.out`C::Private::cleanup() + 52
a.out`C::Private::cleanup:
-> 0x2032b4 <+52>: movl 0x8(%rax), %esi
我认为这可能是 UB 的原因是:
return 0
, c
的生命即将结束。~C()
运行。一旦析构函数的主体(默认)完成,该对象的生命周期就结束了,并且使用该对象是 UB。~std::unique_ptr<Private>
运行。它运行所持有对象的析构函数。~Private()
使用指向不再存在的对象的指针 m_owner
调用成员函数。如果有人能指出这种对对象生命周期的理解是否正确,我将不胜感激。
如果它不是 UB,那么就存在一个单独的实现质量问题(或者我应该在调用 d 指针上的方法之前检查它,但这对于 pimpl 来说似乎有点愚蠢;然后我们得到 if(d)d->cleanup()
,其中一个 STL 实现需要它,而在另一个 STL 实现中这是无用的检查)。
为了提出一个问题:此代码是否在声明 m_owner->cleanup()
中显示 UB (第 9 行)在对象销毁期间 c
?
最佳答案
是的,m_owner
引用的对象的生命周期已经结束,并且当调用 m_owner->cleanup();
时,它的析构函数调用已完成。因此该电话是 UB。
关于c++ - std::unique_ptr、pimpl 和对象生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70832270/
我正在开发一个使用多个 turtle 的滚动游戏。玩家 turtle 根据按键命令在 Y 轴上移动。当危害和好处在 X 轴上移动时,然后循环并改变 Y 轴位置。我尝试定义一个名为 colliding(
我不明白为什么他们不接受这个作为解决方案,他们说这是一个错误的答案:- #include int main(void) { int val=0; printf("Input:- \n
我正在使用基于表单的身份验证。 我有一个注销链接,如下所示: 以及对应的注销方法: public String logout() { FacesContext.getCurren
在 IIS7 应用程序池中有一个设置 Idle-time out 默认是 20 分钟,其中说: Amount of time(in minutes) a worker process will rem
我是一名优秀的程序员,十分优秀!