【问题标题】:Does joining a member thread accessing other members of its parent class in the parent's destructor result in undefined behavior?在父级的析构函数中加入访问其父类的其他成员的成员线程会导致未定义的行为吗?
【发布时间】:2017-03-17 03:37:15
【问题描述】:

我的一位同事声称,一旦对象的析构函数调用开始,线程对对象成员的所有访问(即对象本身的成员)都是 UB。

这意味着如果线程正在访问对象的任何其他成员,则在对象的析构函数期间调用 std::thread::join 是 UB。

我在“对象生命周期”下简要查看了最新的标准草案,但找不到能给我确定答案的内容。

以下代码(on wandbox) 是否引入了未定义的行为标准中阐明这种交互的部分是什么?

struct A 
{
    atomic<bool> x{true};
    thread t;

// Capturing 'this' is part of the issue.
// The idea is that accessing 'this->x' becomes invalid as soon as '~A()' is entered.
//           vvvv
    A() : t([this]
            { 
                while(x) 
                {
                    this_thread::sleep_for(chrono::milliseconds(100)); 
                }
            }) 
    { 
    }

    ~A() 
    { 
        x = false; 
        t.join(); 
    }
};

int main()
{
    A a;
}

【问题讨论】:

  • 没有任何意义。他的意思是在析构函数中删除原始成员指针也是 UB,因为这是在主线程上发生的,或者他的意思是 2 个线程执行析构函数,这意味着竞争条件和不正确的代码。你最好问问他信仰的来源:)
  • "[class.cdtor]/1 对于具有非平凡析构函数的对象,在之后引用对象的任何非静态成员或基类析构函数完成执行会导致未定义的行为。”强调我的。这似乎意味着在析构函数完成执行之前访问成员是可以的。
  • 想一想:你通常在析构函数中所做的一切都取决于那些仍然活着的成员。析构函数没有任何可以处理的参数,它唯一有的是this 所以this-&gt; 更好地引用可用的对象。

标签: c++ multithreading c++11 language-lawyer undefined-behavior


【解决方案1】:

这不是未定义的行为。如果我们查看 [class.dtor]/8 我们有

在执行析构函数的主体并销毁主体内分配的任何自动对象后,类 X 的析构函数调用 X 的直接非变体非静态数据成员的析构函数、X 的直接基类的析构函数,如果X 是最派生类(12.6.2)的类型,它的析构函数调用 X 的虚拟基类的析构函数。

声明类的非静态成员在析构函数体运行后被销毁。这意味着所有成员在析构函数中都处于活动状态,并且操作 x 和调用 join 的行为就像在普通成员函数中一样。唯一的区别是在析构函数的主体运行之后,成员本身将被销毁。

【讨论】:

    【解决方案2】:

    使用 N3337,因为这个问题被标记为 C++11。

    在析构函数执行期间访问类成员似乎没有定义:

    §12.7 [class.cdtor]/1

    对于具有非平凡析构函数的对象,引用任何 析构函数后对象的非静态成员或基类 完成执行会导致未定义的行为。

    虽然有人说

    §12.4 [class.dtor]/15

    一旦为对象调用析构函数,该对象就不再存在

    以下在讨论对象时明确链接到 12.7:

    §3.8 [basic.life]/5

    在对象的生命周期开始之前但在存储之后 对象将占用的位置已分配 38 或者, 在对象的生命周期结束之后和存储之前 被占用的对象被重用或释放,任何指向的指针 对象将或曾经位于的存储位置可能是 使用但仅限于有限的方式。对于正在建造的物体或 破坏,见 12.7。

    【讨论】:

      猜你喜欢
      • 2017-03-27
      • 1970-01-01
      • 2014-07-13
      • 1970-01-01
      • 2014-08-22
      • 1970-01-01
      • 2020-12-04
      • 2011-11-03
      • 2021-11-30
      相关资源
      最近更新 更多