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?
Under GCC compiler you can turn off optimization for selected functions manually with compiler directives like in the example below.
#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.
#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.
ffmpeg (written in C, not C++) addresses this problem by having a wrapper for free
, which zeroes the pointer .
In new code they prefer av_free(&ptr)
over 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.
I know it wouldn't prove anything, but have you seen cases where the compiler optimizes away these pointer-zeroing stores?
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.