← Назад к вопросам
С какой областью памяти работает Garbage Collector?
2.0 Middle🔥 111 комментариев
#Dart
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Garbage Collector и области памяти в Dart/Flutter
Основы памяти в Dart
Dart использует управляемое выделение памяти с автоматической очисткой. Память делится на несколько областей:
Heap (куча) — главная зона ответственности GC
Это основная область, где Garbage Collector работает:
- Все объекты (классы, листы, маппы, строки)
- Все динамические структуры данных
- Все экземпляры, созданные с
new
Пример:
var person = Person(name: "John"); // выделяется в Heap
var items = [1, 2, 3]; // List в Heap
var data = {"key": "value"}; // Map в Heap
GC отслеживает объекты в Heap и удаляет те, на которые нет ссылок.
Stack (стек) — автоматическая очистка
- Локальные переменные примитивных типов
- Ссылки на объекты в Heap
- Параметры функций
- Возвращаемые значения
Пример:
void myFunction() {
int x = 5; // Stack — примитив
var obj = MyClass(); // Stack получает ссылку, сам объект в Heap
}
// После выхода из функции локальные переменные автоматически удаляются
Stack очищается автоматически при выходе из области видимости — GC здесь не нужен.
Как работает Garbage Collector в Dart
Generational GC:
- Young Generation — новые объекты (быстрая сборка)
- Old Generation — долгоживущие объекты (редкая сборка)
Этот подход основан на гипотезе поколений: новые объекты чаще становятся мусором.
Mark-and-Sweep алгоритм:
- Mark фаза — отмечаются живые объекты (из Stack и из других живых объектов)
- Sweep фаза — удаляются неотмеченные объекты
Практический пример утечки памяти
class MyWidget extends StatefulWidget {
@override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
late StreamSubscription subscription;
@override
void initState() {
super.initState();
// ПРОБЛЕМА: подписка держит ссылку на State
subscription = streamController.stream.listen((data) {
// обработка
});
}
@override
void dispose() {
// РЕШЕНИЕ: отписываемся явно перед удалением Widget
subscription.cancel();
super.dispose();
}
}
Без subscription.cancel() GC не сможет удалить Widget, даже если он больше не видим на экране.
Производительность и оптимизация
Избежание частой аллокации:
// Плохо — создаёт новый список каждый фрейм
Widget build(BuildContext context) {
return Column(children: <Widget>[...].toList()); // новый List
}
// Хорошо — переиспользуем список
final List<Widget> _children = [...];
Widget build(BuildContext context) {
return Column(children: _children);
}
Явное управление ресурсами:
// Закрытие потоков, контроллеров, соединений
@override
void dispose() {
_controller.dispose(); // освобождаем контроллер
_streamSubscription.cancel();
super.dispose();
}
Ключевые выводы
- GC работает с Heap, где хранятся все объекты
- Stack автоматический, не требует GC
- Памятью нужно управлять явно — закрывать потоки, подписки, контроллеры
- Generational approach — новые объекты проверяются чаще
- Утечки в Flutter часто из-за незакрытых ресурсов, а не из-за GC