gpt4 book ai didi

c++ - 在单独的线程中与类型的构造函数并行运行成员函数是否是未定义的行为?

转载 作者:行者123 更新时间:2023-12-01 13:30:14 25 4
gpt4 key购买 nike

这是你不应该做的场景,但是 https://timsong-cpp.github.io/cppwp/class.cdtor#4状态:

Member functions, including virtual functions ([class.virtual]), can be called during construction or destruction ([class.base.init]).



如果并行调用这些函数,这是否成立?也就是说,忽略竞争条件,如果 A正在 build 中, frobme在调用构造函数后的某个时间点调用(例如在构造过程中),这仍然是定义的行为吗?

#include <thread>

struct A {
void frobme() {}
};

int main() {
char mem[sizeof(A)];

auto t1 = std::thread([mem]() mutable { new(mem) A; });
auto t2 = std::thread([mem]() mutable { reinterpret_cast<A*>(mem)->frobme(); });

t1.join();
t2.join();
}

作为一个单独的场景,有人还向我指出 A 是可能的。的构造函数来创建多个线程,这些线程可能会在 A 之前调用成员函数函数已完成构造,但这些操作的顺序将更易于分析(您知道在构造函数中生成线程之后才会发生竞争)。

最佳答案

这里有两个问题:您的特定代码和您的一般问题。

在您的特定代码中,即使在最好的情况下(其中 t2t1 之后执行),由于创建和使用之间缺乏同步,您也存在数据竞争。无论执行顺序如何,这都会使您的代码成为 UB。

在一般问题中,让我们假设类型的构造函数传递 this指向某个其他线程的指针,然后该线程调用其上的函数,并且切换本身已正确同步。调用成员函数的其他线程是否会被视为数据竞争?

好吧,如果另一个线程调用一个函数来读取成员值或在切换点之后由构造函数写入的其他数据,或者如果构造函数访问成员或成员写入的其他数据,那肯定会发生数据竞争被调用的函数。也就是说,如果同时执行的代码之间没有数据竞争。

假设这两种情况都不是,那么一切都应该没问题(大多数情况下。可以定义 A,这样您的 reinterpret_cast 不会返回指向您在该存储中创建的 A 的可用指针; you'd need to launder it )。可以访问正在构建/销毁的对象,但只能访问 in certain ways.坚持这些方法,你应该没问题……有一个可能的捕获。

标准中没有关于对象初始化完成时的数据竞争,只有内存位置冲突。一旦对象完全构建,virtual 的行为如果动态类型是从提供给另一个线程的类派生的类,则函数可能会根据更改的 vtable 指针而更改。我不相信在对象模型部分对此有明确的说明。

另外,请注意 C++20 为 class.cdtor 添加了一条特殊规则。 :

During the construction of an object, if the value of the object or any of its subobjects is accessed through a glvalue that is not obtained, directly or indirectly, from the constructor's this pointer, the value of the object or subobject thus obtained is unspecified.

关于c++ - 在单独的线程中与类型的构造函数并行运行成员函数是否是未定义的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60712964/

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