Перейти к содержимому

StackOverflow во время инициализации

✅ Паттерн воспроизведён в Political World 💥 Troubleshooting

StackOverflow во время запуска, инициализации мира, создания государства или другого первого setup часто означает, что небольшая группа методов косвенно вызывает сама себя.

A()
B()
C()
A()
B()
C()
...

В исходнике вовсе не обязательно будет очевидный вызов вида A() { A(); }.

В реальном моде гораздо чаще встречается косвенная рекурсия.

Getter инициализирует отсутствующее состояние

Заголовок раздела «Getter инициализирует отсутствующее состояние»
Thing GetThing()
{
if (thing == null)
SetThing(CreateThing());
return thing;
}

Если SetThing() в итоге снова вызывает GetThing(), цикл готов.

SetState()
→ event/callback
→ listener читает State
→ getter пытается инициализировать
→ SetState()

Prefix/Postfix может вызвать метод, который в итоге снова приводит к пропатченному методу.

Исправление не всегда заключается в «убрать Harmony». Сначала нужно доказать, где именно замыкается цикл.

  1. Найдите самый маленький повторяющийся набор методов в stack/log.
  2. Нарисуйте между ними стрелки.
  3. Отметьте, какие функции читают состояние, а какие его меняют.
  4. Ищите read-функцию, которая скрытно мутирует или инициализирует объект.
  5. Сделайте отдельную одноразовую функцию инициализации с guard.
  6. Пусть getter возвращает данные, а не пытается автоматически починить весь граф объектов.
  7. Повторно протестируйте именно тот сценарий первой инициализации, который падал.

Guard может защитить от случайного повторного входа:

private bool _initializing;
void EnsureInitialized()
{
if (_initialized || _initializing)
return;
_initializing = true;
try
{
// инициализация без getter, способных снова войти сюда
_initialized = true;
}
finally
{
_initializing = false;
}
}

Guard не заменяет понимание причины. Это дополнительная защита после того, как зависимости инициализации приведены в нормальный вид.

Political World воспроизвёл этот паттерн, когда у нового государства отсутствовали данные формы правления.

См.: Political World — рекурсия при инициализации правительства.