Представьте себе, что вы работаете над довольно сложной программой. Например, с мудрёными математическими расчётами. Вы её компилируете, запускаете в первый раз, она выдаёт ожидаемый результат и работает без ошибок. Скорее всего, в такой ситуации опытный программист сильно удивится и начнет перепроверять свой код: так не бывает, чтобы сложная программа сразу скомпилировалась, заработала, да ещё и не содержала багов.
Действительно, такое случается довольно редко. Как однажды сказал один очень хороший разработчик с моей прошлой работы: «Код хороший, жаль только, что не работает». Если у вас получается сразу писать сложные программы, которые не содержат ошибок, то вы — уникальный специалист.
Баги в программах — это любимая тема программистского фольклора. Они сопровождают разработчиков всю жизнь. Ошибки бывают разные: совсем глупые описки, которые отлавливаются при первой же компиляции; более серьёзные, которые можно найти при прогоне на тестовых примерах; системные, которые связаны со сложными аспектами взаимодействия разных систем. Самые неприятные — это плавающие ошибки, которые появляются неожиданно и так же неожиданно исчезают. Этакие привидения программной среды.
Для того, чтобы отловить все баги в программах, придумано множество различных методик и приёмов. Серьёзные программы проходят через несколько этапов тестирования: функциональное, регрессионное, интеграционное. Есть множество систем автоматизации тестирования. Придуманы даже специальные методики разработки, нацеленные на то, чтобы минимизировать количество ошибок ещё на уровне создания программного кода.
Несмотря на все эти ухищрения, баги всё равно прорываются в релизные сборки. Тогда они становятся проблемой пользователей и службы технической поддержки. Такие ошибки часто бывают некритичными: кнопка не работает, картинка не на месте. Они доставляют пользователям много неприятных минут, мешают работать, но не приводят к серьёзным последствиям.
Но иногда возникают такие баги, которым удалось укорениться в базовых системах: в процессорах, ядре ОС. Их обнаруживают не сразу, и они имеют гораздо более критические последствия. О нескольких таких эпических багах я и хочу рассказать.
1900 год всё ещё високосный
Самое неприятное — когда ты в своей программе случайно находишь явную ошибку, исправляешь её и программа после этого перестаёт работать.
bash.im
В 1983 году компания Lotus Software выпустила для компьютеров IBM PC своё знаменитое приложение для работы с таблицами, которое называлось «Lotus 1-2-3». В своё время эта программа считалась самым надёжным и быстрым табличным процессором. К сожалению, она содержала маленькую, но очень серьёзную ошибку.
По какой-то причине 1900 год в ней считался високосным. Пользователи сообщили об этой ошибке, но её так никто и не исправил. Разработчики утверждали, что исправление этого бага приведёт к необходимости переписывать почти весь код программы. Почему — это вопрос, на который нет ответа. Календари и даты — это вообще больная тема для многих разработчиков.
В 1995 году компанию Lotus Software приобрела фирма IBM, но к тому времени уже набирал свои обороты Microsoft Excel. Многие пользователи переходили с Lotus 1-2-3 на Microsoft Excel, а это значит, что нужно было обеспечить их совместимость. Именно для обеспечения совместимости разработчики Microsoft приняли осознанное взвешенное решение аккуратно транслировать эту ошибку в пакет Microsoft Office.
Как утверждали сотрудники Microsoft, недостатки, которые могут возникнуть при исправлении этой ошибки, значительно перевешивают преимущества. Её исправление привело бы к тому, что изменились бы данные в тысячах файлов пользователей Excel.
Вы можете спросить: «Кто же использует в своих таблицах даты в начале XX века?» Оказалось, что исправление ошибки затронет и другие даты. Как написано на сайте Microsoft, если ошибку исправить, то «почти все даты в текущих Microsoft Excel и других документах будут уменьшены на один день».
Считается, что исправление ошибки повлияет на даты после 1 марта 1900, поэтому Microsoft не хочет рисковать, ведь книг Excel с такими датами «сотни тысяч». Кроме того, «исправление этого поведения нарушает совместимость последовательной даты между Microsoft Excel и другими программами, которые используют даты». Это тоже может стать проблемой для пользователей.
В некоторых источниках утверждается, что эта ошибка была исправлена ещё в 2007 году, но в моём рабочем Excel 2016 она всё ещё воспроизводится. Проведём эксперимент: если у вас есть Excel, откройте новую таблицу и введите в ячейки две даты: 29.02.1900 и 29.02.1901. Первая тут же выравнивается по правому краю, а значит Excel воспринимает эту строку как валидную дату. Вторая дата так и останется строкой — такой даты не бывает даже по версии Lotus. Так что баг, о котором известно уже больше 30 лет, всё ещё с нами.
Рассеянный процессор
Не печалься, Барт, все совершают ошибки. Просто твои публичные и дорого стоят.
Гомер Симпсон
Мы все давно привыкли к тому, что сложные математические программы могут содержать ошибки. Это, конечно, неприятно, но этого можно ожидать. Где-то программист забыл перевести градусы в радианы, где-то ошибся в размерности. Такие баги бывают и их несложно исправить — главное вовремя их отловить.
Но когда речь заходит о процессоре, ошибок в расчётах мы никак не ожидаем. Мы твёрдо верим, что уж на аппаратном уровне всё должно быть чётко и надёжно. К сожалению, так бывает далеко не всегда. Довольно широкую известность получила ошибка, возникавшая при выполнении операций над числами с плавающей запятой в процессорах Intel Pentium. Этот баг обнаружили и обнародовали в 1994 году.
Процессор при использовании ассемблерной команды FDIV в некоторых случаях неправильно делил одно число на другое. Не всегда, только для определённых чисел, но, согласитесь, что это слабое утешение. Одно дело, если деление выполнено неправильно при расчёте домашнего бюджета. А если это расчёт траектории спутника?
Вот очень наглядный пример:
-
4195835 / 3145727 × 3145727 = 4195835 — правильный расчёт;
-
4195835 / 3145727 × 3145727 = 4195579 — то, что выдавал процессор Intel.
Компания Intel в этой истории повела себя не лучшим образом. Её руководство знало об ошибке, но попросту скрывало её. Более того, когда о проблеме стало известно, Intel заявила, что для бесплатной замены процессора пользователи должны были доказать, что им эта замена необходима.
Это вызвало такую волну недовольства и критики, что представители компании пошли на попятную: принесли публичные извинения и заявили, что каждый может обменять процессор бесплатно. Всё это стоило компании 475 миллионов долларов. О подробностях этой истории можно почитать здесь.
Замена процессора — дело хлопотное. Так что программисты исправили проблему самым простым доступным им способом: в компиляторах Delphi и Visual Basic была добавлена проверка наличия этой ошибки и её автоматическое исправление на уровне приложения. Если ошибка обнаруживается, то программа просто корректирует результат выполнения операции FDIV. Конечно, это несколько замедляет работу приложений, но правильный результат дороже.
После того, как весь этот кошмар закончился, руководство фирмы Intel раздало главным инженерам компании брелоки с впаянным злополучным процессором и надписью: «Кризисы разрушают плохие компании. Хорошие компании переживают их. Великие компании от кризисов становятся лучше».
Купертино с нашими итальянскими товарищами
— Тупой словарь: «калевалу» знает, а «коленвал» — нет.
— Он не тупой, просто гуманитарный.
bash.im
От дат и расчётов перейдём к проверке орфографии. Представьте себе, что словарь замены неправильных слов содержит ошибку. Хотя многим это даже не придётся представлять — почти все рано или поздно попадают в ловушку автозамены на телефоне. В сети есть множество примеров смешных автозамен, которые торопливые авторы сообщений не успевают заметить перед отправкой.
Здесь же речь пойдёт не о быстром обмене сообщениями в мессенджерах, а о государственных документах. Ошибка, о которой я хочу рассказать, оставила свой след во многих официальных бумагах.
В английском языке есть вполне обычное слово «cooperation» — «сотрудничество». По правилам английского языка его можно написать и так: «co-operation». В моём словаре Lingvo есть обе версии написания. Соответственно, и программы проверки орфографии английских текстов должны содержать оба варианта.
К сожалению, долгое время в некоторых приложениях (например, в Microsoft Word примерно с 1989 года) вариант «cooperation» в списке правильных слов отсутствовал. В общем-то, ничего страшного в этом бы не было, если бы умная система не предлагала заменить вариант «cooperation» на «Cupertino» — название города в Калифорнии.
Теперь представим, что у многих пользователей настроена автозамена неправильно набранных слов на правильный вариант. Стоит ли удивляться, что в архивах ООН, НАТО, Евросоюза сохранилось немалое количество официальных документов со словом «Купертино» вместо слова «сотрудничество».
Вот вам несколько примеров:
-
Купертино с нашими итальянскими товарищами было очень плодотворным.
-
Азиатская ассоциация регионального Купертино.
-
Презентация афро-немецкого Купертино.
Эта ошибка была настолько распространена, что даже получила своё собственное название: «эффект Купертино». Есть и другие примеры подобных автозамен в английском языке. Американский лингвист Бенжамин Зиммер даже коллекционирует такие случаи. В его коллекции есть пример публикации из газеты New York Times, в которой вместо «Voldemort» написано «Voltmeter».
Очень умный ксерокс
— Добрый день, а у нас ксерокс не печатает.
— Он и не должен печатать, он делает копии.
— Ой, да, спасибо!
bash.im
Вернёмся обратно к аппаратному обеспечению. Как вам ксерокс, который при копировании заменяет цифры в оригинале? Вам кажется, что такое невозможно? К сожалению, в современной гонке за оптимизацией алгоритмов работы офисной техники такой фантастический вариант стал реальностью.
Мы привыкли к тому, что ксерокс, хоть и технологичное устройство, но в общем его функции достаточно банальны — сделать копию с оригинала. Интуитивно мы предполагаем, что ксерокс работает как связка сканера с принтером: отсканировали изображение, получили картинку и отправили её на принтер. Именно так, видимо, и работали ранние ксероксы.
Но устройства усложнялись, появились МФУ, в которых уже была встроена довольно сложная программная начинка. Видимо, в этом и заключалась причина ошибки, которую в 2013 году обнаружил немец Дэвид Крисель в МФУ фирмы Xerox.
Совершенно случайно Дэвид заметил, что при ксерокопировании некоторых документов с цифрами устройство периодически заменяло цифру «6» на «8», а цифру «2» на «1». Согласитесь, что это крайне странное поведение для ксерокса. Тем более, что в нём был отключён алгоритм распознавания текста и пользователь выполнял простое ксерокопирование.
Оказалось, что в устройстве использовался алгоритм компрессии графики JBIG2. Этот алгоритм фактически выполняет распознавание текста и заменяет графическое изображение на символы. При появлении схожих символов алгоритм подбирал им замену из библиотеки уже распознанных букв и цифр.
Понятно, что распознавание текста позволяет существенно сжать исходный файл. Другой вопрос, зачем этот алгоритм применялся при простом ксерокопировании. Интересно, что при недостаточном качестве сканирования алгоритм может заменить ещё и «2» на «7» или даже «1» на «3».
Компания Xerox повела себя аналогично Intel — не сразу признала свою ошибку. Поупиравшись какое-то время, Xerox всё-таки выпустили обновлённую прошивку для своих устройств. Но многочисленные пользователи должны её скачать и установить, а это делают далеко не все.
Кроме того, этот же алгоритм используется не только в большинстве современных устройств фирмы Xerox, но и в устройствах и программах других фирм. Так что проверяйте свои ксерокопии. Ведь баг действительно серьёзный. Вдруг при очередном ксерокопировании устройство заменит, например, номер вашего паспорта или сумму вашей зарплаты в бухгалтерской ведомости.
Ядерный Ганди
Кстати, о «Цивилизации». Поначалу мне нравилась третья часть, до того самого момента, как рота элитных мушкетёров, окопавшихся в городе, сбила ракету с ядерной боеголовкой.
bash.im
Последняя ошибка в нашем топе называется «Ядерный Ганди», конечно, она не столь критична, но очень уж необычная. Появилась она при весьма странных обстоятельствах. Сначала прошёл слух, что она есть. Потом оказалось, что её нет. Потом разработчики «для прикола» добавили этот баг в свою программу.
По легенде в ранних версиях популярной стратегии Sid Meier’s Civilization существовала ошибка, из-за которой один из самых миролюбивых лидеров цивилизаций Махатма Ганди при определённом стечении обстоятельств превращался в самого агрессивного персонажа и не задумываясь использовал ядерные боеголовки против других цивилизаций.
Обычно эту ошибку описывают так: для каждого лидера в игре использовалась переменная, которая хранила уровень его агрессии. Этот уровень мог меняться в зависимости от игровой ситуации и действий других лидеров и игрока.
Для Ганди, понятное дело, по умолчанию был установлен минимальный уровень агрессии — 1. При переходе к демократии уровень агрессии по игровому алгоритму снижался на два пункта. Уровень агрессии Ганди при этом должен был стать отрицательным, но для хранения этого показателя использовалась однобайтовая беззнаковая целочисленная переменная. А это означало, что после такой операции уровень агрессии становился равным 255. Из-за этого бедный Ганди становился в 25 раз более агрессивным, чем самые отрицательные лидеры в игре.
Разработчики игры утверждали, что всё это только миф. Сам Сид Мейер говорил, что этого бага в ранних версиях игры никогда не существовало, что в коде применялись знаковые целочисленные переменные, и что государственный строй по игровому алгоритму вообще не влиял на агрессивность лидеров.
Миф об этой ошибке появился примерно в 2012 году и постепенно стал распространяться в сети. В итоге разработчики решили пошутить и специально добавили эту ошибку в качестве пасхалки в новую версию игры Sid Meier’s Civilization V. В ней Ганди остался таким же незлобливым и миролюбивым, как Нед Фландерс в сериале «Симпсоны», но при этом вероятность создания и применения ядерного оружия у него установлена максимальная — 12. Это самое большее из возможных значений.
Так ошибка под названием «Ядерный Ганди» из мифа стала реальностью. А ещё это источник множества мемов в сети. Сам же Махатма Ганди был очень мудрым человеком. Когда-то он сказал: «Ценность идеала в том, что он удаляется, по мере того как мы приближаемся к нему».
Статья была впервые опубликована на другом ресурсе 1 июня 2021.
Автор: Александр Клименков