Подтвердить что ты не робот

Что происходит при столкновении стека и кучи

Мне любопытно узнать, что происходит, когда стек и куча сталкиваются. Если кто-нибудь столкнулся с этим, объясните, пожалуйста, сценарий.

Спасибо заранее.

4b9b3361

Ответ 1

На современных языках, работающих на современной ОС, вы получите либо переполнение стека (ура!), либо malloc() или sbrk() или mmap(), если вы попытаетесь увеличить кучу. Но не все программное обеспечение является современным, поэтому давайте посмотрим на режимы отказа:

  • Если стек превращается в кучу, типичный компилятор C будет молча перезаписывать структуры данных кучи. На современной ОС будет существовать одна или несколько защищенных страниц , которые предотвращают неограниченный рост стека. Пока объем памяти на страницах защиты не меньше размера растущей записи активации процедуры, ОС гарантирует вам segfault. Если вы используете DOS на машине без MMU, вы, вероятно, будете закрыты.

  • Если куча растет в стек, операционная система всегда должна знать об этой ситуации, и какой-то системный вызов не удастся. Реализация malloc() почти наверняка замечает ошибку и возвращает NULL. Что происходит после этого зависит от вас.

Я всегда удивляюсь желанию авторов компилятора надеяться, что ОС поставит защитные страницы на место, чтобы предотвратить переполнение стека. Конечно, этот трюк работает хорошо, пока вы не начнете иметь тысячи потоков, каждый со своим собственным стеком...

Ответ 2

Это зависит от платформы. На многих платформах это на самом деле не может быть вообще (куча и стек выделены на разных страницах и не будут встречаться два раза.

Имейте в виду, что идея роста кучи вверх и стека, растущего вниз, только концептуальна. На очень маленьких системах (например, на старых 8-битных микрошах, которые запускали CP/M), а также на некоторых ПОС и других системах с плоской памятью (без MMU или любой другой виртуальной или защищенной памяти), то куча и стек могли бы быть фактически таким образом. В этом случае поведение будет undefined... но оно почти наверняка потерпит крах, как только код попытается вернуться к некоторому адресу в верхней части поврежденного стека или последует косвенным указателем из одной части кучи в другую или...

В любом случае вы не увидите его на любой современной рабочей станции общего назначения или на сервере. Вы нажмете ограничение на ресурсы и получите сбои в malloc, или вы столкнетесь с виртуальной памятью, и в конечном итоге система будет разбиваться на дрожащую кучу "нажми на красный переключатель".

Ответ 3

Во времена, подобные тем, нужно время обратиться к мудрым словам доктора Эгона Шпенглера....

  • Dr. Эгон Шпенглер: Там что-то очень важное, я забыл сказать вам.
  • Dr. Питер Венкман: ​​Что?
  • Dr. Эгон Шпенглер: Не позволяйте куче сталкиваться со стеком.
  • Dr. Питер Венкман: ​​Почему?
  • Dr. Эгон Шпенглер: Было бы плохо.
  • Dr. Питер Венкман: ​​Я немного расплывчатый в целом "хороший/плохой". Что значит "плохо"?
  • Dr. Эгон Шпенглер: Попытайтесь представить всю жизнь, поскольку вы знаете, что она мгновенно останавливается, и каждая молекула в вашем теле взрывается со скоростью света.
  • Dr. Ray Stantz: Полное воспроизведение протонов!
  • Dr. Питер Венкман: ​​Это плохо. Хорошо. Хорошо, важный совет безопасности. Спасибо, Эгон.

Ответ 4

Вы получаете исключение из памяти или исключение стека, если вам повезет. Если вам не повезло, программа переходит в недопустимую память и либо выбрасывает неправильное исключение памяти. Если вам очень не повезло, программа продолжает и уничтожает то, что не должна, и вы никогда не знаете, почему ваша программа не удалась.

Наконец, конечно, вселенная может треснуть.

Ответ 5

Если произойдет переполнение стека/кучи, вы получите ошибку сегментации или выделение памяти. Вот пример:

void recursiveFun ()
{
    static int i;
//  char *str= (char *)malloc (100);
    printf ("%d\t", i++);
    recursiveFun ();
// free (str);
}

Предположим, вы вызываете функцию выше, она закончится из стека, и программа выйдет из строя. Теперь удалите прокомментированные строки и снова вызовите функцию, вы обнаружите, что ошибка сегментации происходит за меньшее время и меньше рекурсии, чем предыдущая. [В моей тестовой среде переполнение стека произошло после рекурсии 5237765 в первом случае, тогда как во втором сценарии это произошло после рекурсии 2616325.]