Вступление:
Я пытаюсь быстро взломать исправление старого кода и использовать расширение 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 отстой, иначе не понятно, если «» отключит все оптимизации функции.
Прежде всего это довольно плохая идея для начала, так что вы можете подумать над всем дизайном. Но если вы вынуждены придерживаться этого, то что-то вроде:
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
так что это не может быть оптимизировано.
Windows API имеет
BOOL WINAPI IsBadReadPtr(_In_ const VOID *lp,_In_ UINT_PTR ucb);
BOOL WINAPI IsBadWritePtr(_In_ LPVOID lp, _In_ UINT_PTR ucb);
Вам нужно прочитать раздел замечаний, но ваш случай может быть достаточно простым, чтобы этих функций хватило. Независимо от того, в разделе замечаний даются полезные советы, когда вы пытаетесь обрабатывать небезопасные указатели самостоятельно.
Из ответов на подобные вопросы здесь, в SO, кажется, что это:
Лучший источник информации, который я нашел, это вопрос / ответы здесь:
Проверьте, указывает ли указатель на выделенную память в куче
Наиболее разумным мне кажется: