gpt4 book ai didi

c++ - 为必须可平凡复制的 volatile 结构分配一个值

转载 作者:搜寻专家 更新时间:2023-10-31 00:24:31 24 4
gpt4 key购买 nike

我有一个 struct 需要将一些实例声明为 volatile 因为它们表示与驱动程序共享的内存(即内存可能会被外部进程更改我的 C++ 程序)。 struct 也需要可平凡复制,因为我将与一些要求其所有输入都可平凡复制的代码共享它的实例。这两个要求似乎意味着我不可能安全地将新值分配给 structvolatile 实例。

这是我正在尝试做的一个简化示例:

struct foo {
uint16_t a;
uint16_t b;
};

int main() {
static_assert(std::is_trivially_copyable<foo>::value, "Oh no!");
volatile foo vfoo;
foo foo_value{10, 20};
vfoo = foo_value;
}

如果我尝试使用 g++ 编译它,它会在 vfoo = foo_value 行失败,并显示“错误:将‘volatile foo’作为‘this’参数传递会丢弃限定符。”根据this question ,那是因为隐式定义的赋值运算符没有声明为 volatile,我需要定义一个 volatile 复制赋值运算符才能分配给 volatile 对象。但是,如果我这样做:

struct foo {
uint16_t a;
uint16_t b;
volatile foo& operator=(const foo& f) volatile {
if(this != &f) {
a = f.a;
b = f.b;
}
return *this;
}
}

然后静态断言失败,因为如果 foo 具有用户定义的赋值运算符,则它不再是平凡可复制的。

因为编译器显然已经决定不允许我执行这个非常简单的操作,所以我目前正在使用这个解决方法:

int main() {
static_assert(std::is_trivially_copyable<foo>::value, "Oh no!");
volatile foo vfoo;
foo foo_value{10, 20};
memcpy(const_cast<foo*>(&vfoo), &foo_value, sizeof(foo));
std::atomic_signal_fence(std::memory_order_acq_rel);
}

显然,放弃 volatile 不是一个好主意,因为这意味着编译器现在可以违反 volatile 应该强制执行的语义(即每个代码中的读取和写入被转换为实际读取或写入内存)。我试图通过用 memcpy 替换赋值来缓解这种情况,这应该意味着编译器无法优化写入(即使它认为写入对程序的其余部分不可见),并在赋值后添加内存栅栏,这意味着编译器不能选择将写入延迟到很晚。

这是我能做的最好的吗?是否有更好的解决方法可以更接近 volatile 的正确语义?或者有没有办法让编译器让我为 volatile 结构分配一个新值而不使该结构不可平凡复制?

最佳答案

如果您不一定需要使用赋值运算符(即,如果您认为 memcpy 替代方案可行),那么您可以改为编写一个非运算符赋值函数:

volatile foo& volatile_assign(volatile foo& f, const foo& o) {
if(&f != &o) {
f.a = o.a;
f.b = o.b;
}
return f;
}

如果您愿意,可以使用成员函数。

我是根据您的示例编写的,但请考虑自赋值检查是否对可变语义有效。不应该重写相同的值吗?我不认为这种情况是有效的,除非对象实际上是非 volatile 的,否则我们将通过非 volatile 引用读取 volatile 对象(也许您还需要对其他操作数进行 volatile 限定)。

关于c++ - 为必须可平凡复制的 volatile 结构分配一个值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58016326/

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