Возможный дубликат:
Что такое ошибка?
Может ли кто-нибудь рассказать мне, как и почему переполнение стека и переполнение кучи на самом деле происходит в программах, и как преодолеть переполнение стека в программировании - как его избежать?
Возможный дубликат:
Что такое ошибка?
Может ли кто-нибудь рассказать мне, как и почему переполнение стека и переполнение кучи на самом деле происходит в программах, и как преодолеть переполнение стека в программировании - как его избежать?
void stack_overflow(const char *x)
{
char y[3];
strcpy(y, x);
}
void heap_overflow(const char *x)
{
char *y = malloc(strlen(x));
strcpy(y, x);
}
Обе функции попираются за выделенное пространство.
Если вы вызываете stack_overflow("abc")
, он копирует 4 символа (включая нуль) в пространство, выделенное для 3 символов. Что происходит после этого, зависит от того, где был нанесен ущерб. Переменная y
находится в стеке, поэтому это переполнение стека.
Независимо от того, как вы вызываете heap_overflow()
, он запрашивает слишком мало байтов из кучи, а затем пишет за его пределами. Что коварно в том, что некоторое время - даже большую часть времени - похоже, будет работать, потому что система кучи выделяет больше места, чем вы запрашиваете. Однако вы можете попирать контрольные данные, а затем все ставки отключены.
Переполнение кучи очень мало и трудно обнаружить. Переполнение стека может быть небольшим (не существует, если переданная строка достаточно коротка) или драматична. Вы обычно получаете более драматические эффекты, когда пишете дальше за выделенным пространством, но любая запись за пределами выделенного пространства приводит к поведению undefined - все может случиться.
Вы гарантируете, что нет проблем, зная, насколько большой объект, который вы копируете, и сколько места для его получения, и убедитесь, что вы не копируете больше материала, чем есть место. Всегда, каждый раз.
"переполнение стека" отличается от "переполнения буфера на основе стека". Первый из-за слишком глубоких записей активации, например, прерывания рекурсивного вызова. Последнее является ошибкой программного обеспечения из-за недостаточной проверки границ, которая является наиболее часто используемой уязвимостью.
Переполнение стека:
static void f(void) { f() ; }
int main() { f() ; }
Переполнение кучи:
#include <stdlib.h>
int main() { while (1) malloc (1000) ; }
Изменить. По-видимому, это не то, что означает переполнение кучи. См. Комментарии ниже.