Следующий метод отладки имеет весьма узкое применение и в большинстве случаев может оказатся неподходящим. Описанное решение пришло в результате поиска проблемы в чужом коде, написанном в ужасном стиле (смесь С++ и С). Речь пойдет о защите памяти с помощью функции VirtualProtect. Эта функция позволяет изменить режим доступа к страницам памяти: только чтение, копирование по записи, полное отсутсвие доступа и далее. Полный список флагов можно найти в документации.
Для целей отладки интересен флаг PAGE_NOACCESS. Он позволяет ловить запись или, что более важно, чтение за пределами некоторой валидной области памяти. Для удобного применения VirtualProtect был создан следующий класс:
struct protect_mem_t {
protect_mem_t( void* addr, size_t size ) : addr(addr), size(size), is_protected(FALSE) {
protect();
}
~protect_mem_t() { release(); }
BOOL protect() {
if ( !is_protected ) {
is_protected = VirtualProtect( addr, size, PAGE_NOACCESS, &old_protect );
}
return is_protected;
}
BOOL release() {
if ( is_protected )
is_protected = !VirtualProtect( addr, size, old_protect, &old_protect );
return !is_protected;
}
protected:
void* addr;
size_t size;
BOOL is_protected;
DWORD old_protect;
};Применять его можно следующим образом:
const size_t PAGE_SIZE = 4096;
int main()
{
const size_t var_size = 1024*96; // 1024*96 - некоторый размер. Конкретное значение здесь только в качестве примера.
const size_t guard_size = PAGE_SIZE*2-var_size%PAGE_SIZE;
__declspec(align(4096)) char some_var[var_size+guard_size];
protect_mem_t guard( &some_var[var_size], PAGE_SIZE );
some_var[5] = 20; // that's ok
char x = some_var[5]; // that's ok
char y = some_var[1024*96+1024]; // access violation
return 0;
}В приведенном примере, как и в реальной программе, была добавлена защитная область памяти прямо на стеке. Удачной отладки.

2 коммент.:
Интересная штука, спасибо
Спасибо за полезный приём!
Отправить комментарий