Чтобы избежать этого в моих собственных проектах (в Windows), я написал свой собственный распределитель памяти, который просто назывался VirtualAlloc и VirtualFree. Он выделил дополнительную страницу для каждого запроса, выровнял ее по левому краю последней страницы и использовал VirtualProtect
для генерации исключения при каждом доступе к последней странице. Это обнаружило за пределами доступа, даже просто читает, на месте.
Отказ от ответственности: я ни в коем случае не был первым, кто получил эту идею.
Например, если страницы имеют размер 4096 байт и был вызван new int[1]
, распределитель будет:
- Выделите 8192 байта (необходимо 4 байта, что составляет одну страницу, а дополнительная страница защиты приносит общее количество до 2 страниц)
- Отметить последнюю страницу как недоступную
- Определить адрес для возврата (последняя выделенная страница начинается с 4096 ... 4096 - 2 = 4092)
Следующий код:
main() {
int *array = new int[10];
return array[10];
}
будет генерировать нарушение доступа на месте.
У него также была опция (время компиляции) для обнаружения обращений за пределами левой стороны выделения (т. Е. Массива [-1]), но ошибки такого рода казались редкими, поэтому я использовал опцию.