【发布时间】:2015-08-01 21:32:01
【问题描述】:
我正在开发一个多平台、多编译器库。该库具有以下宏:
#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
在 GCC 下,上面的代码可以用来驯服优化器。
尽管该函数称为MEMORY_BARRIER,但重要的部分是标记为volatile 的内联汇编。这就是在 GCC、Clang 和 Intel 下驯服优化器的部分。
编辑:内联程序集不会驯服 Clang 上的优化器,即使 Clang 通过定义 __GNUC__ 声称是 GCC。见LLVM Bug 15495 - dead store pass ignores memory clobbering asm statement。
宏的使用是一个handle 类。 handle 提供了一个级别和间接性,我们正在尝试诱导一个 NULL 指针取消引用以帮助定位错误(一些手放弃)。为了实现我们的目标,我们需要确保优化器不会删除死存储(m_p = NULL;):
template <class T> handle<T>::~handle()
{
delete m_p;
m_p = NULL;
MEMORY_BARRIER();
}
我不想使用 volatile 演员表,因为 (1) 我不相信它对限定符的正确使用(取自与 Clang 和 GCC 开发人员的交互),并且 (2) 它看起来volatile cast 是 C++ 中未定义的行为(参见 Approved way to avoid lvalue cast warnings and errors?)。
内存屏障是否会驯服 Microsoft 平台上的优化器?
【问题讨论】:
-
作为替代解决方案,如果您想将
m_p设置为零而不担心它会被优化掉,您可以在Windows 为目标时使用SecureZeroMemory()。对于其他目标,您也许可以调用其他 API 或汇编函数? -
@Michael - 是的,同意。如果我可以重新使用内存屏障代码,那么它可以通过将实现特定的细节隐藏在宏后面(并且不需要更多的宏和
_Pragma,以及伴随它的所有条件)来很好地整理事情。
标签: c++ visual-studio optimization memory-management cl.exe