Если вам уже стыдно смотреть в глаза тестировщику или git blame снова указал на вас, успокойтесь, не вы одни совершаете ошибки. Сегодня мы расскажем о самых дорогих ошибках программирования, стоивших сотни миллионов долларов.
Катастрофа Mars Climate Orbiter: языковой барьер систем измерений (1999)
История Mars Climate Orbiter — это трагический пример того, как самая простая человеческая ошибка может привести к гибели высокотехнологичного космического аппарата и потере многомиллионной миссии. Аппарат, являвшийся ключевой частью программы Mars Surveyor, предназначался для изучения марсианского климата и атмосферы, помогая в подготовке будущих пилотируемых миссий.
26 сентября 1999 года, когда Mars Climate Orbiter должен был выйти на расчётную орбиту Марса, он неожиданно исчез. Расследование показало, что аппарат вошёл в атмосферу Марса слишком низко и слишком быстро, что привело к его мгновенному сгоранию в плотных слоях.
Потрясающе простая ошибка крылась в несоответствии систем измерений между двумя командами разработчиков:
- Команда Lockheed Martin, ответственная за разработку и передачу данных о тяге двигателя, использовала английскую систему измерений, оперируя фунтами-силы (lbf).
- Команда Лаборатории реактивного движения NASA (JPL), ответственная за навигацию и расчёт орбиты, ожидала получить эти данные в метрической системе СИ, в ньютонах (N).
Разница в расчётах между фунтами-силы и ньютонами составляет примерно 4,45 раза. Из-за этого несогласованного обмена данными все орбитальные расчёты были неверными. Система технически работала «правильно», но с неправильными единицами, что не позволило ей вовремя обнаружить ошибку.
Стоимость миссии оценивалась в 327 миллионов долларов (в других источниках часто фигурирует цифра 125 млн долларов, относящаяся к стоимости самого аппарата). Потеря Mars Climate Orbiter стала горьким уроком для NASA. Формально никто не был уволен, но инцидент привёл к глубокой переоценке внутренних протоколов и стандартов:
- Была введена жёсткая политика использования исключительно метрической системы (СИ) во всех будущих космических миссиях.
- Были ужесточены требования к проверке и согласованию интерфейсов между различными командами и подрядчиками.
- Ошибка, не выявленная на Земле, показала необходимость более строгого и многоуровневого финального тестирования.
История Mars Climate Orbiter до сих пор является хрестоматийным примером в инженерии и программировании, подчёркивая, что даже при работе лучших научных групп мира человеческий фактор и отсутствие элементарной проверки могут привести к катастрофическим последствиям.
Integer Overflow: как переполнение переменной уничтожило «Ариан-5»
Катастрофа ракеты-носителя «Ариан-5» в 1996 году является одним из самых известных и дорогостоящих примеров критической ошибки в программном обеспечении. Ракета Европейского космического агентства взорвалась спустя всего 37 секунд после старта, что привело к потере четырёх спутников Cluster (которые были на борту «Ариан-5») и убыткам в размере около 370 миллионов долларов.
Основная причина сбоя крылась в повторном использовании кода от её предшественницы — ракеты «Ариан-4». Модуль инерционной системы ориентировки (ИСО), отвечавший за навигацию, был унаследован от старой модели. Разработчики полагали, что раз он прекрасно работал на «Ариан-4», он подойдёт и для новой ракеты. Однако «Ариан-5» была значительно мощнее и быстрее.
Критический момент наступил при попытке преобразования значения горизонтальной скорости. Это значение хранилось в виде 64-битного числа с плавающей запятой, но код от «Ариан-4» пытался преобразовать его в 16-битную целую переменную со знаком (диапазон от −32 768 до +32 767). Для более медленной «Ариан-4» этого диапазона было достаточно, но скорость «Ариан-5» быстро превысила максимальное допустимое значение +32 767. Произошло переполнение переменной (integer overflow).
Вместо того чтобы обработать это исключение, программа системы наведения просто аварийно завершила работу. Сбой основного компьютера привёл к автоматическому переключению на резервный модуль, но в нём стоял идентичный унаследованный код, который немедленно вызвал такой же сбой. Отказ обеих систем навигации привёл к тому, что ракета получила некорректные команды на рулевые поверхности.
Неверные команды спровоцировали резкое отклонение от курса. Из-за высокой скорости это привело к критической аэродинамической нагрузке, разрушению конструкции и, в конечном итоге, к самоликвидации ракеты.
После катастрофы ESA и Arianespace сделали следующие ключевые выводы и внедрили изменения:
- Полный отказ от слепого повторного использования кода без анализа новых условий эксплуатации.
- Обязательный независимый аудит и ревью всего ПО, особенно унаследованного.
- Введение строгих требований по проверке диапазонов данных и обязательной обработке исключений (включая переполнения) в критическом ПО.
- Переход на более современные языки (с Ada 83 на Ada 95 и позже), где контроль переполнения включён по умолчанию.
- Усиление симуляций и тестов на максимальных реальных нагрузках, а не только на «типичных» сценариях «Ариан-4».
- Создание независимой комиссии по расследованию программных сбоев (по образцу авиационных расследований).
Инцидент с «Ариан-5» остаётся одним из наиболее известных примеров дорогостоящей ошибки в программном обеспечении критически важной системы и привёл к существенным изменениям в практике разработки и тестирования бортового ПО.
Крах Knight Capital Group: 45 минут, стоившие полмиллиарда долларов
В августе 2012 года компания Knight Capital Group, один из крупнейших игроков на рынке электронной и высокочастотной торговли (HFT) на Нью-Йоркской фондовой бирже (NYSE), пережила катастрофический технический сбой, который привёл к её фактическому банкротству. Инцидент, длившийся всего 45 минут, стал одним из самых громких примеров уязвимости автоматизированных финансовых систем.
Сбой произошёл 1 августа 2012 года, когда Knight Capital готовилась к запуску новой торговой функции NYSE Retail Liquidity Program. Техническая команда проводила обновление своего торгового программного обеспечения. Критическая ошибка была допущена в процессе развёртывания (деплоя). Обновление не было развёрнуто равномерно на всех серверах: на одном из восьми серверов осталась старая, неиспользуемая годами функция — тестовый флаг «PowerPeg» («мёртвый» код). При запуске нового кода на этом сервере активировалась старая тестовая логика.
Сразу после открытия торгов активированный алгоритм на одном сервере вышел из-под контроля и начал совершать безудержные аномальные транзакции. Бот совершал миллионы ошибочных сделок, покупая акции по завышенным ценам и немедленно продавая их по заниженным, буквально за секунды теряя деньги. В течение 45 минут система Knight Capital совершила несколько миллионов нежелательных сделок. К тому моменту, когда инженеры смогли остановить систему, компания уже потеряла 440–460 миллионов долларов. Эта сумма практически сравнялась с квартальной выручкой компании.
Убытки были настолько колоссальными, что акции Knight Capital обвалились более чем на 75 % за день, поставив компанию на грань немедленного банкротства. Несмотря на привлечение экстренного финансирования в размере 400 млн долларов, компания потеряла доверие рынка и в декабре 2012 года была поглощена конкурентами, перестав существовать как независимая структура.
Инцидент с Knight Capital стал самым дорогим софтверным багом в истории высокочастотной торговли и преподал финансовой индустрии ряд ключевых уроков:
- Во-первых, процессы развёртывания (деплоя) должны быть полностью автоматизированы и защищены от человеческих ошибок.
- Во-вторых, устаревший или неиспользуемый код должен быть полностью удалён из системы, чтобы исключить его случайную активацию.
- В-третьих, необходима возможность быстро и надёжно остановить вышедший из-под контроля алгоритм и откатить неверное развёртывание.
- И наконец, алгоритмы должны проходить тщательное тестирование в среде, максимально приближённой к реальному рабочему окружению.
Крах Knight Capital подчеркнул, что в эпоху HFT даже незначительная ошибка в коде может привести к многомиллионным потерям в считанные минуты.
Заключение
Мы все хотим писать чистый, надёжный код и верить, что «у нас-то всё продумано». Но эти три истории напоминают очень простую вещь: безошибочных систем не бывает. Бывает только разная цена ошибки — от пары часов дебага до 460 миллионов долларов, которые исчезли за 45 минут, или ракеты, которая разорвалась на высоте 4 км, потому что кто-то решил, что «на Ариане-4 работало — и здесь сойдёт».
Поэтому каждый раз, когда лень писать обработку исключения, проверку диапазона, тесты на максимальных нагрузках или просто удалить мёртвый флаг из репозитория — вспомните, что где-то в этот момент может крутиться не ваш локальный дев-сервер, а аппарат за 327 миллионов, ракета за 370 или трейдинг-бот, который одним циклом сожрёт всю прибыль компании за квартал.
Пусть ваши самые дорогие баги остаются на уровне «потратил вечер на фикс» и никогда не попадают в новости, отчёты NASA и учебники по software engineering. Проверяйте единицы измерения, не оставляйте мёртвый код, пишите обработку overflow и деплоите аккуратно. Это дешевле, чем учить весь мир на своих ошибках.