Что такое куча в памяти и зачем она нужна
Что проверяют
Понимаете ли вы, где на самом деле живут объекты в .NET и что делает сборщик мусора. Вопрос звучит как основы, но быстро переходит в разговор о поколениях, о структурах и об утечках при наличии сборщика.
Как отвечать
Куча это область памяти процесса для объектов, чьё время жизни не привязано к кадру вызова. Стек дёшев и строго дисциплинирован: кадр создаётся при вызове и уничтожается при возврате, размер невелик и задан для потока заранее. Как только объект должен пережить метод или его размер неизвестен на этапе компиляции, он уходит в кучу.
В .NET экземпляры классов, массивы и строки размещаются в управляемой куче, а ссылки на них лежат там, где объявлены. Сборщик поколенческий: новые объекты попадают в нулевое поколение, пережившие сборку переходят выше, и основная масса мусора собирается дёшево. Крупные массивы идут в отдельную кучу больших объектов, которая по умолчанию не уплотняется, и фрагментация копится именно там.
Стоит подчеркнуть правило размещения значимых типов: struct не живёт на стеке по своей природе. Поле-структура внутри класса лежит в куче вместе с ним, захваченная замыканием переменная переезжает в сгенерированный класс, состояние асинхронного метода при первом ожидании тоже оказывается в куче.
Где спотыкаются
Повторяют формулу, что ссылочные типы на куче, а значимые на стеке. Место определяется не видом типа, а контекстом объявления, и именно поэтому упаковка, замыкания и асинхронные состояния нагружают сборщик там, где этого не ждали.
Считают, что при наличии сборщика утечек не бывает. Освобождается только недостижимое, а статические коллекции, неотписанные события и живые таймеры держат ссылки сколь угодно долго. Отдельная история неуправляемые ресурсы: файлы и соединения закрываются через IDisposable, а не сборщиком.
Путают ручной вызов сборки с оптимизацией. Он сбивает эвристику поколений и обычно делает хуже; настоящие рычаги это меньше короткоживущих объектов, пулы буферов, работа через Span без копий и структуры там, где значение мало и живёт недолго.