Как запретить компилятору оптимизировать загрузку в переменную, которая никогда не используется

Вступление:
Я пытаюсь быстро взломать исправление старого кода и использовать расширение MSVC __try, чтобы проверить, указывает ли какой-либо ptr на некоторую допустимую память или * ptr вызовет нарушение памяти (в этом случае я прекращаю обработку этого ptr).
Поэтому я написал что-то вроде:

bool checkIsPtrPointingToValidAddress(const void *ptr)
{
__try
{
auto cpy = *((int*)ptr); // force mem access...
if ( (cpy ==42) && ((rand()+rand()+rand()+rand()+ rand()) == 1))
{
FILE* pFile = fopen ("tempdata.dat","w"); //... by unlikely but possible action
fputs (" ",pFile);
fclose (pFile);
}
return true;
}
__except(1)
{
return false;
}

}

Дело в том, что моё решение заставить доступ к мему кажется странным, безобразным, и в качестве бонуса я не уверен, что это правильно. Также, пожалуйста, не надо отключать оптимизацию для всего проекта, так что это не вариант. А документация для оптимизации прагмы на MSDN отстой, иначе не понятно, если «» отключит все оптимизации функции.

1

Решение

Прежде всего это довольно плохая идея для начала, так что вы можете подумать над всем дизайном. Но если вы вынуждены придерживаться этого, то что-то вроде:

volatile auto copy1 = *((char*)ptr);  // using int* here could lead to aliasing violations, so better char in the general case..
volatile auto copy1 = *((char*)ptr);
if (copy1 != copy2)
throw std::exception("Cannot happen, but compiler cannot know this");

безусловно, должен сделать свое дело. Компилятор не может исключить чтение или предположить, что они идентичны, поэтому должен выполнить код. С другой стороны, если не считать проблем с многопоточностью или других интересных сценариев, мы знаем, что эти два чтения будут идентичными, поэтому исключение не будет вызвано.

добавленной

По правилам стандарта, любое чтение или запись в энергозависимый объект представляет собой наблюдаемое поведение (например, побочный эффект), поэтому даже следующего должно быть достаточно:

volatile auto copy = *((char*)ptr);

Это включает в себя запись в энергозависимый объект copyтак что это не может быть оптимизировано.

8

Другие решения

Windows API имеет

BOOL WINAPI IsBadReadPtr(_In_ const VOID *lp,_In_ UINT_PTR ucb);
BOOL WINAPI IsBadWritePtr(_In_ LPVOID lp, _In_ UINT_PTR ucb);

Вам нужно прочитать раздел замечаний, но ваш случай может быть достаточно простым, чтобы этих функций хватило. Независимо от того, в разделе замечаний даются полезные советы, когда вы пытаетесь обрабатывать небезопасные указатели самостоятельно.

4

Из ответов на подобные вопросы здесь, в SO, кажется, что это:

  • зависит от компилятора
  • нетривиальный

Лучший источник информации, который я нашел, это вопрос / ответы здесь:

Проверьте, указывает ли указатель на выделенную память в куче

Наиболее разумным мне кажется:

  1. статический анализ (valgrind), отладка, рефакторинг
  2. использовать некоторые взломать для вашего компилятора
  3. проверьте коммерческое решение, рекламируемое в этом ответе
0
По вопросам рекламы [email protected]