Для чего нужен стек кроме хранения локальных переменных
Что проверяют
Понимаете ли вы, как исполняется программа, настолько, чтобы читать трассировку упавшего теста и отличать переполнение стека от других падений. Для QA это прикладной вопрос: стек вызовов вы видите в каждом отчёте об ошибке. Следом часто спрашивают про разницу стека и кучи.
Как отвечать
Локальные переменные лишь часть кадра стека. Остальное:
- адрес возврата: куда передать управление, когда функция закончится;
- аргументы и сохранённые регистры: часть аргументов идёт через регистры, остальное вместе с состоянием вызывающей функции сохраняется в кадре;
- рекурсия: каждый вызов получает свой кадр, поэтому глубина рекурсии ограничена размером стека;
- раскрутка при ошибке: при исключении или
panicсреда идёт по кадрам вверх, ищет обработчик и выполняет очистку. В Go так срабатывают функции, отложенные черезdefer, и в нихrecoverможет перехватить панику; - трассировка: стек вызовов в момент ошибки и есть stack trace, по нему находят строку и цепочку вызовов;
- потоки: у каждого потока свой стек, поэтому локальные переменные одного потока не видны другим, пока на них не передали ссылку.
Про Go добавьте конкретику. Стек горутины начинается с нескольких килобайт и растёт по мере нужды, предел по умолчанию на 64-битных системах 1 ГБ, дальше программа падает с goroutine stack exceeds в сообщении. Где окажется переменная, на стеке или в куче, решает escape-анализ компилятора, его вывод покажет go build -gcflags=-m.
Если интервьюер имел в виду стек как структуру данных LIFO, назовите применения: отмена действий, проверка скобок, обход в глубину, кнопка «назад» в браузере.
Где спотыкаются
Читают трассировку не с того конца. В Go и Java самый свежий вызов сверху, в Python внизу, о чём прямо говорит строка most recent call last. Не зная этого, заводят баг не на тот модуль.
Путают переполнение стека с нехваткой памяти в куче. Бесконечная рекурсия в тесте даёт StackOverflowError в Java или RecursionError в Python при лимите по умолчанию 1000, а не OutOfMemoryError.
Смешивают стек вызовов и структуру данных «стек» в одном ответе, так и не объяснив ни то, ни другое.