DLL函数调用周边Store/Load重排合法性及原子操作疑问
关于DLL函数调用与内存重排的疑问
我需要借助atomic_ref来保证内存操作的Store/Load顺序,但由于客户使用C++11标准,无法在产品API的头文件中直接使用atomic_ref,因此计划将相关逻辑实现为DLL中的函数。但我不确定编译器是否会对带有release语义存储的DLL函数调用前后的Store/Load操作进行重排,从而破坏预期的内存顺序。
我查阅了DLL函数调用前后Store/Load重排的合法性相关资料,确认编译器可以自由重排外部翻译单元(比如DLL)中函数调用前后的存储和加载操作。
基于此,我认为以下生产环境中的代码无法保证producer函数里的存储顺序:
#include <atomic> #include <cassert> #include <thread> bool flag = false; int data = 0; // 假设以下命名空间中的函数实现于独立DLL namespace defined_in_another_dll { void flag_ready(bool& b) { std::atomic_ref<bool>(b).store(true, std::memory_order_release); } bool is_ready(bool& b) { return std::atomic_ref<bool>(b).load(std::memory_order_acquire); } } void producer() { data = 42; defined_in_another_dll::flag_ready(flag); // 这个调用可能和data的赋值重排? } void consumer() { while (!defined_in_another_dll::is_ready(flag)); assert(data == 42); // 可能触发断言,因为producer中的重排! } int main() { std::thread t1(producer); std::thread t2(consumer); t1.join(); t2.join(); }
我的疑问是:为什么编译器可以对DLL函数调用周边的赋值操作进行重排,但直接使用atomic_ref的producer函数(如下)却被认为是合法的?谁能保证该原子存储会被始终内联,让优化器识别到编译器屏障?如果该原子存储最终编译成函数调用,那情况不就和DLL版本一样了吗?这让我十分困惑。
void producer() { data = 42; std::atomic_ref<bool>(flag).store(true, std::memory_order_release); }
内容的提问来源于stack exchange,提问作者Ibraim Ganiev
相关产品推荐
相关产品推荐

