вторник, 9 июня 2009 г.

Хозяйке на заметку

Следующий метод отладки имеет весьма узкое применение и в большинстве случаев может оказатся неподходящим. Описанное решение пришло в результате поиска проблемы в чужом коде, написанном в ужасном стиле (смесь С++ и С). Речь пойдет о защите памяти с помощью функции 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;
}

В приведенном примере, как и в реальной программе, была добавлена защитная область памяти прямо на стеке. Удачной отладки.

Комментировать в ВКонтакте