内存障碍是否驯服了微软的优化器?

时间:2015-08-01 21:32:02

标签: c++ visual-studio optimization memory-management cl.exe

我正在开发一个多平台,多编译器库。该库具有以下宏:

#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和英特尔下驯服优化器的部分。

编辑 :内联汇编并没有驯服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强制转换在C ++中是未定义的行为(参见Approved way to avoid lvalue cast warnings and errors?)。

内存障碍是否驯服了Microsoft平台上的优化器?

2 个答案:

答案 0 :(得分:2)

在GCC编译器下,您可以使用编译器指令手动关闭所选函数的优化,如下例所示。

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

在VC编译器下,您可以使用编译器指令手动关闭所选函数的优化,如下例所示。

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

也许你可以用这个技巧来得到你想要的东西?

不幸的是,我现在不知道如何在clang / llvm或Intel Compiler下做类似的技巧。

答案 1 :(得分:0)

ffmpeg(用C编写,而不是C ++)通过a wrapper for free, which zeroes the pointer来解决这个问题。

在新代码中,他们更喜欢av_free(&ptr)而不是av_free(ptr)

如果存在释放后使用状态,编译器将无法证明它是一个死存储并消除它,我想。如果允许编译器假定对析构函数中的成员变量的写入是死存储,那么这可能在C ++中不起作用。

我知道它不能证明什么,但你看过编译器优化掉这些指针归零存储的情况吗?