简体   繁体   English

内存屏障会驯服微软的优化器吗?

[英]Does a memory barrier tame Microsoft's optimizer?

I'm working on a multi-platform, multi-compiler library.我正在开发一个多平台、多编译器库。 The library has the following macro:该库具有以下宏:

#if defined(_MSC_VER) && (_MSC_VER >= 1400)
# pragma intrinsic(_ReadWriteBarrier)
# define MEMORY_BARRIER() _ReadWriteBarrier()
#elif ...
#elif defined(__GNUC__)
# define MEMORY_BARRIER() __asm__ __volatile__ ("" ::: "memory")
#else
# define MEMORY_BARRIER()
#endif

Under GCC, the code above can be used to tame the optimizer.在 GCC 下,上面的代码可以用来驯服优化器。 Though the function is called MEMORY_BARRIER , the important part is the inline assembly marked volatile .尽管该函数称为MEMORY_BARRIER ,但重要的部分是标记为volatile的内联程序集。 That's the part that tames the optimizer under GCC, Clang and Intel.这就是驯服 GCC、Clang 和 Intel 下的优化器的部分。

EDIT : The inline assembly does not tame the optimizer on Clang, even though Clang claims to be GCC by defining __GNUC__ .编辑:内联程序集不会驯服 Clang 上的优化器,即使 Clang 通过定义__GNUC__声称是 GCC。 See LLVM Bug 15495 - dead store pass ignores memory clobbering asm statement .请参阅LLVM 错误 15495 - 死存储传递忽略内存破坏 asm 语句

The use of the macro is a handle class.宏的使用是一个handle类。 The handle provides one level and indirection, and we are trying to induce a NULL pointer dereference to help locate bugs (some hand waiving). handle提供了一个级别和间接性,我们正在尝试引入一个 NULL 指针解引用来帮助定位错误(一些人放弃)。 To achieve our goal, we need to ensure the optimizer does not remove the dead store ( m_p = NULL; ):为了实现我们的目标,我们需要确保优化器不会删除死存储( m_p = NULL; ):

template <class T> handle<T>::~handle()
{
    delete m_p;
    m_p = NULL;

    MEMORY_BARRIER();
}

I don't want to use a volatile cast because (1) I don't believe its the correct use of the qualifier (taken from interactions with the Clang and GCC devs), and (2) it appears the volatile cast is undefined behavior in C++ (see Approved way to avoid lvalue cast warnings and errors? ).我不想使用volatile强制转换,因为 (1) 我不相信它正确使用了限定符(取自与 Clang 和 GCC 开发人员的交互),并且 (2) 看起来volatile强制转换是未定义的行为在 C++ 中(参见Approved way to avoid lvalue cast warnings and errors? )。

Does a memory barrier tame the optimizer on Microsoft platforms?内存屏障是否会驯服 Microsoft 平台上的优化器?

Under GCC compiler you can turn off optimization for selected functions manually with compiler directives like in the example below.在 GCC 编译器下,您可以使用编译器指令手动关闭所选函数的优化,如下例所示。

#pragma GCC push_options
#pragma GCC optimize ("O0")
static inline void MEMORY_BARRIER() {
    // your code
}
#pragma GCC pop_options

Under VC compiler you can turn off optimization for selected functions manually with compiler directives like in the example below.在 VC 编译器下,您可以使用编译器指令手动关闭所选函数的优化,如下例所示。

#pragma optimize( "", off )
static inline void MEMORY_BARRIER() {
    // your code
}
#pragma optimize( "", on ) 

Maybe you can use this tricks to get what you want?也许你可以用这个技巧来得到你想要的?

Unfortunately I do not now how to do similar trick under clang/llvm or Intel Compiler.不幸的是,我现在不知道如何在 clang/llvm 或 Intel Compiler 下做类似的技巧。

ffmpeg (written in C, not C++) addresses this problem by having a wrapper for free , which zeroes the pointer . ffmpeg(用 C 编写,而不是 C++)通过free一个包装器来解决这个问题,它将指针归零

In new code they prefer av_free(&ptr) over av_free(ptr) .在新代码中,他们更喜欢av_free(&ptr)不是av_free(ptr)

If there is a use-after-free condition, the compiler won't be able to prove it's a dead store and eliminate it, I guess.如果存在释放后使用条件,我猜编译器将无法证明它是一个死存储并消除它。 This might not work in C++, if the compiler is allowed to assume that writes to member variables in a destructor are dead stores.如果允许编译器假定对析构函数中成员变量的写入是死存储,则这在 C++ 中可能不起作用。

I know it wouldn't prove anything, but have you seen cases where the compiler optimizes away these pointer-zeroing stores?我知道这不能证明任何事情,但是您是否见过编译器优化掉这些指针归零存储的情况?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM