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.
Though the function is called MEMORY_BARRIER, the important part is the inline assembly marked volatile. That's the part that tames the optimizer under GCC, Clang and Intel.
EDIT: The inline assembly does not tame the optimizer on Clang, even though Clang claims to be GCC by defining __GNUC__. See LLVM Bug 15495 - dead store pass ignores memory clobbering asm statement.
The use of the macro is a handle class. The handle provides one level and indirection, and we are trying to induce a NULL pointer dereference to help locate bugs (some hand waiving). To achieve our goal, we need to ensure the optimizer does not remove the dead store (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?).
Does a memory barrier tame the optimizer on Microsoft platforms?
m_pto zero with no concern about it being optimized away, you can useSecureZeroMemory()when Windows is the target. For other targets you can perhaps call some other API or an assembly function? - Michael Burr_Pragma, and all the conditionals that accompany it). - jww