2015-08-01 5 views
2

Я работаю над многоплатформенной библиотекой с несколькими компиляторами. Библиотека имеет следующий макрос:Является ли барьер памяти ручным оптимизатором Microsoft?

#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.

EDIT: Рядный сборка не приручить оптимизатор на Clang, хотя Clang утверждает, что GCC определяя __GNUC__. См. 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?

+1

В качестве альтернативного решения, если вы хотите установить «m_p» в ноль, не заботясь об оптимизации, вы можете использовать «SecureZeroMemory()», когда Windows является целью. Для других целей вы можете назвать некоторые другие API или функцию сборки? –

+0

@ Майкл - да, согласился.Если бы я мог повторно использовать код барьера памяти, тогда он хорошо подбирает вещи, скрывая конкретные детали реализации, которые соответствуют макросу (и без необходимости в дополнительных макросах и '_Pragma', и все условные обозначения, которые его сопровождают). – jww

ответ

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.

+0

Да, я отошел от этого точного кода. – jww

+0

Да, я отошел от этого точного кода (но я забыл сказать вам, почему ...). Visual Studio позволяет управлять оптимизацией для изданий Professional и Enterprise, а не выпусков Learning и Community (IIRC). – jww

0

ffmpeg (написанный на C, а не C++) решает эту проблему, имея a wrapper for free, which zeroes the pointer.

В новом коде они предпочитают av_free(&ptr) над av_free(ptr).

Если есть условие без использования, компилятор не сможет доказать, что это мертвый магазин и устранить его, я думаю. Это может не работать на C++, если компилятору разрешено предположить, что записи в переменные-члены в деструкторе являются мертвыми хранилищами.

Я знаю, что это ничего не докажет, но видели ли вы случаи, когда компилятор оптимизирует эти магазины для обнуления указателей?

+1

* «... вы видели случаи, когда компилятор оптимизирует эти магазины с указателем?» - да. – jww

+0

Случается ли это, если вы по назначению используете бесплатное использование? Возможно, если функция-член возвращает адрес переменной-члена в код, который сохраняет его. Или даже просто наличие переменной-члена public. –

Смежные вопросы