Mandelbug: що це, причини нестабільності та методи пошуку

Автор: IT Sectr Опубліковано: 2026-07-29 Час читання: 9 хв

Mandelbug — це тип програмної помилки, поведінка якої хаотична і залежить від безлічі факторів: стану пам'яті, порядку виконання потоків, зовнішніх умов. Назва походить від прізвища математика Бенуа Мандельброта, творця теорії фракталів, де найменша зміна початкових умов призводить до кардинально іншого результату. За даними Вікіпедії (2026), Mandelbug є одним із найскладніших для діагностики типів дефектів, оскільки його неможливо відтворити за фіксованим сценарієм.

Головне

  • Mandelbug — хаотична помилка, яка відтворюється нерегулярно і залежить від стану системи.
  • Назва пов'язана з фракталами Мандельброта — найменша зміна вхідних даних змінює поведінку бага.
  • Діагностика Mandelbug потребує спеціальних інструментів: логування, профілювання та стрес-тестування.
  • Основні причини — гонки потоків, стан гонки, невизначена поведінка та проблеми з пам'яттю.
  • Запобігання досягається через імутабельність даних, блокування та ретельне проєктування конкурентного доступу.

Що таке Mandelbug?

Mandelbug — це програмна помилка з нелінійною, хаотичною поведінкою. На відміну від Bohrbug, який стабільно відтворюється за однакових вхідних даних, Mandelbug може проявлятися в одній сесії та повністю бути відсутнім в іншій за тих самих зовнішніх умов.

Термін введений Джимом Греєм та Андреасом Ройтером у 1993 році як частина класифікації програмних помилок. Mandelbug був названий на честь Бенуа Мандельброта — математика, який відкрив фрактальні множини, де поведінка системи експоненційно залежить від початкових умов.

Основна небезпека Mandelbug полягає в його непередбачуваності. Тестувальник може виконати один і той самий сценарій п'ятдесят разів, і баг проявиться лише на п'ятдесят перший — або не проявиться взагалі. Це створює хибне відчуття стабільності системи.

Визначення за Греєм та Ройтером

Згідно з класифікацією з книги «Transaction Processing: Concepts and Techniques», Mandelbug — це дефект, який не задовольняє умову детермінованості. Його поведінка залежить від факторів, які розробник не може контролювати: порядку планування потоків, фрагментації пам'яті, кешування.

Походження назви Mandelbug

Назва Mandelbug походить від прізвища Бенуа Мандельброта — математика, який ввів поняття фрактала та досліджував хаотичні системи. Множина Мандельброта демонструє вражаючу властивість: нескінченно малі зміни початкових умов призводять до принципово інших результатів.

Грей та Ройтер провели пряму аналогію: як фрактал Мандельброта чутливий до початкових умов, так і Mandelbug чутливий до стану системи в момент виконання. Зміна порядку алокації пам'яті або кванта часу планувальника потоків — і баг зникає чи з'являється.

У професійному слензі Mandelbug також називають «багом-привидом» або «плаваючим багом». Він — головний ворог QA-інженерів, оскільки не піддається стандартній методиці «відтворив — зарепортив — перевірив виправлення».

Характеристики Mandelbug

Mandelbug має унікальний набір властивостей, які відрізняють його від усіх інших типів програмних помилок. Розглянемо кожну з них.

Нелінійність

Поведінка Mandelbug нелінійна. Він може не проявлятися тисячі разів, а потім раптово виникнути за, здавалося б, ідентичних умов. Ця властивість робить його практично невиявним на етапі функціонального тестування.

Залежність від стану

Mandelbug залежить від внутрішнього стану системи: розміру купи, порядку алокації об'єктів, заповненості кешу процесора. Навіть додавання налагоджувального printf може змінити таймінги та «вилікувати» баг, перетворивши його на Heisenbug.

Ефект метелика

Термін «ефект метелика» застосовний до Mandelbug повною мірою. Зміна одного рядка коду в зовсім іншому модулі може усунути або, навпаки, викликати Mandelbug у непов'язаній частині застосунку через зміну патерну алокації пам'яті.

Основні причини Mandelbug

Причини виникнення Mandelbug пов'язані з конкурентним виконанням та недетермінованою поведінкою сучасних обчислювальних систем.

Гонки потоків

Класична race condition — коли два потоки одночасно звертаються до спільного ресурсу без синхронізації. Результат залежить від того, який потік виконається першим, а порядок виконання не гарантований операційною системою.

Проблеми з кешуванням

Кеш процесора та кеш браузера можуть зберігати застарілі дані. Якщо застосунок покладається на кешоване значення, яке вже неактуальне, виникає Mandelbug — помилка, яка проявляється лише на «холодному» або «гарячому» кеші.

Невизначена поведінка компілятора

Деякі конструкції мови (наприклад, неініціалізовані змінні в C/C++) призводять до невизначеної поведінки. Компілятор може згенерувати різний код залежно від рівня оптимізації, прапорців збірки та версії компілятора.

Як знайти Mandelbug у проєкті

Пошук Mandelbug потребує системного підходу та спеціалізованих інструментів. Звичайні методи налагодження тут не працюють, оскільки баг невідтворюваний на вимогу.

Логування на всіх рівнях

Докладне логування — єдиний спосіб зафіксувати Mandelbug. Кожен потік має записувати свій стан, часові мітки та порядок операцій. Після збою логи аналізуються для виявлення патерну.

Стрес-тестування

Навантажувальне тестування з багаторазовим повторенням операцій підвищує ймовірність прояву Mandelbug. Чим більше ітерацій, тим вищий шанс, що рідкісна комбінація умов призведе до збою.

Спеціалізовані інструменти

ThreadSanitizer, Helgrind та інші аналізатори гонок потоків здатні виявляти потенційні Mandelbug без їхнього фактичного відтворення. Вони аналізують код статично та знаходять місця, де можлива race condition.

cpp
// Потенційний Mandelbug: race condition на спільному лічильнику
int counter = 0;

void increment() {
    // Два потоки можуть читати лічильник одночасно
    counter++;  // race condition тут
}

У цьому прикладі Mandelbug може проявитися лише за певного збігу обставин — коли обидва потоки одночасно викликають increment(). У 99% випадків код працює коректно, створюючи хибне почуття безпеки.

Mandelbug vs Heisenbug: у чому різниця

Початківці-розробники часто плутають Mandelbug та Heisenbug. Хоча обидва типи належать до нестабільних помилок, між ними є фундаментальна відмінність.

КритерійMandelbugHeisenbug
Причина нестабільностіХаотичний стан системиСаме налагодження змінює поведінку
Поведінка без налагоджувачаПроявляється рідко, але непередбачуваноПроявляється стабільно до спроби налагодження
Поведінка в налагоджувачіМоже зникнути або змінитисяМайже гарантовано зникає
Типова причинаRace condition, таймінгиОптимізація компілятора, таймери
Інструмент пошукуThreadSanitizer, логиАналіз дампів, дизасемблер

Mandelbug хаотичний за своєю природою, а Heisenbug — детермінований, але змінює поведінку під спостереженням. Відмінність важлива для вибору стратегії налагодження.

Приклад Mandelbug у коді

Розглянемо типовий Mandelbug в Android-застосунку, пов'язаний з гонкою потоків під час роботи з SharedPreferences.

java
public class UserPreferences {
    private final SharedPreferences prefs;

    public synchronized void updateScore(int delta) {
        int current = prefs.getInt("score", 0);
        current += delta;
        prefs.edit().putInt("score", current).apply();
    }
}

На перший погляд код коректний: метод синхронізований. Однак SharedPreferences — це синглтон у процесі, і синхронізація не захищає від паралельних викликів з різних потоків, які отримали однакове значення current до того, як один із них встиг записати нове значення. У результаті один інкремент втрачається.

Цей Mandelbug може не проявлятися тижнями, поки два потоки випадково не викличуть updateScore одночасно з мінімальним розривом. Після виявлення виправлення тривіальне — використати атомарну операцію або базу даних з транзакціями.

Часті запитання

Чим Mandelbug відрізняється від звичайного плаваючого бага?

Mandelbug — це підклас плаваючих багів із яскраво вираженою хаотичною природою. Звичайний плаваючий баг може мати зрозумілу, але рідкісну причину, тоді як Mandelbug демонструє нелінійну залежність від безлічі важковловимих факторів.

Чому Mandelbug складно відтворити?

Складність відтворення Mandelbug пов'язана з його залежністю від мікроскопічних деталей стану системи: порядку алокації пам'яті, планування потоків операційною системою, заповненості кешів процесора. Ці фактори неможливо контролювати з коду застосунку.

Які інструменти допомагають знайти Mandelbug?

Найбільш ефективні інструменти: ThreadSanitizer (TSan), Valgrind Helgrind для C/C++, для Java — утиліти аналізу гонок (Intel Inspector, FindBugs), для багатопотокового коду — статичні аналізатори та стрес-тести з рандомізацією таймінгів.

Чи може Mandelbug бути пов'язаний з пам'яттю?

Так, проблеми з пам'яттю — одна з головних причин Mandelbug. Витоки пам'яті, фрагментація купи, використання після звільнення (use-after-free) та неініціалізована пам'ять створюють умови, за яких поведінка програми стає хаотичною та непередбачуваною.

Як захиститися від Mandelbug на етапі проєктування?

Імутабельність даних — найкращий захист. Якщо дані не можуть бути змінені після створення, гонки потоків виключені. Також допомагають: явні контракти синхронізації, використання атомарних типів, ізоляція конкурентного доступу за блокуваннями та черги повідомлень.

Підсумки

  • Mandelbug — хаотична програмна помилка, яка не піддається детермінованому відтворенню через залежність від стану системи.
  • Назва походить від прізвища Бенуа Мандельброта, чиї фрактали ілюструють чутливість до початкових умов.
  • Основні причини — гонки потоків, невизначена поведінка, проблеми з кешуванням та фрагментація пам'яті.
  • Діагностика потребує логування, стрес-тестування та спеціалізованих аналізаторів (ThreadSanitizer).
  • Відмінність від Heisenbug: Mandelbug хаотичний, Heisenbug зникає при спробі налагодження.
  • Unit-тести рідко допомагають виявити Mandelbug — потрібні інтеграційні та навантажувальні тести.
  • Рекомендація: проєктуйте багатопотоковий код з імутабельними даними та явними блокуваннями.

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також