РАЗРАБОТКА

Как один NOP спас Word 97 от неуловимого сбоя

В конце разработки Word 97 инженеры Microsoft нашли сбой, который исчезал под отладчиком. Исправить его удалось одним NOP и бинарным патчем.

✍️ Редакция iTech News | 29.08.2026 | ⏱ 5 мин | Источник: The Register
🔗

В конце цикла разработки Word 97 команда Microsoft поймала баг, который вел себя как плохая шутка: тестовый сценарий довольно стабильно ронял приложение, но стоило подключить отладчик, и сбой Word 97 исчезал без следа. Для разработчиков это не просто занятная байка из 1990-х, а очень узнаваемый сюжет про хрупкость стека, зависимость софта от железа и цену «маленьких» решений накануне релиза.

Об этой истории рассказал ветеран Microsoft Рэймонд Чен, сообщает The Register. По его словам, дефект всплыл почти под занавес выпуска Word 97, когда пространство для маневра уже минимально: продукт близок к релизу, набор инструментов зафиксирован, а любая замена компилятора или серьезная правка может породить пачку новых проблем. Хуже всего было то, что баг не давался нормальной диагностике. В лаборатории падение воспроизводилось скриптом, но как только инженеры пытались посмотреть на него через отладчик, проблема исчезала. Для команды это был плохой сигнал: если ошибка уже вылезает в тестах и при этом прячется от инструментов, у пользователей она, скорее всего, будет проявляться чаще и больнее.

Дальше история превращается в учебник по инженерной паранойе. Команда начала обсуждать использование ICE, то есть In-Circuit Emulator, аппаратного средства, которое подменяет процессор и позволяет ставить точки останова фактически внутри эмулируемого чипа. Для обычных прикладных разработчиков такая техника выглядела почти мифическим артефактом из мира низкоуровневой отладки. Но в ситуации, когда программные инструменты бессильны, приходится спускаться на уровень ниже и проверять уже не только код, но и то, как конкретная последовательность инструкций взаимодействует с процессором. Именно это и произошло: расследование в итоге вывело команду сначала на конкретного производителя CPU, а затем на errata, то есть документированную ошибку самого процессора.

Здесь начинается самая интересная часть для тех, кто любит повторять, что «железо давно абстрагировано». Нет, не абстрагировано. Даже в зрелом коммерческом продукте можно уткнуться в ситуацию, когда исходный код формально корректен, компилятор не ругается, тесты в целом проходят, а приложение падает из-за неудачной последовательности машинных инструкций на определенном CPU. По словам Чена, используемый в тот момент компилятор уже умел обходить проблемную комбинацию инструкций. Но был нюанс: к тому моменту toolchain для релиза уже зафиксировали. Обновить компилятор на поздней стадии значило фактически перетрусить значительную часть бинарников и открыть дверь для новых, куда менее предсказуемых дефектов. Для продукта масштаба Word такой шаг перед выпуском выглядел слишком рискованным.

Поэтому инженеры выбрали путь, который сегодня многим покажется одновременно элегантным и немного пугающим: они начали искать в уже собранных бинарниках конкретные фрагменты кода, способные вызвать сбой Word 97 на проблемных процессорах. Один такой участок нашли. Чтобы не менять поведение программы шире необходимого, команда не стала пересобирать продукт новым компилятором, а внесла точечный бинарный патч: в опасную последовательность инструкций вставили один NOP, то есть команду «ничего не делать». На уровне исходников это выглядит почти как анекдот. На уровне машинного кода это может менять тайминг, выравнивание или порядок исполнения достаточно, чтобы обойти аппаратный дефект. И иногда именно такая микроскопическая правка отделяет «успешный релиз» от «почему у клиентов падает редактор документов».

История цепляет не только ностальгией по Word 97, который сам по себе был важным релизом: именно в этой версии Microsoft активно продвигала Clippit, более известного как Clippy, и Visual Basic for Applications. Цепляет она тем, что очень точно показывает реальную иерархию рисков в разработке. На презентациях запоминаются новые функции и дружелюбные ассистенты. В боевой инженерии релиз часто спасает не фича, а человек, который вовремя отказался от «красивого» решения в пользу самого узкого и проверяемого. Обновить компилятор целиком выглядело бы чище с точки зрения процесса. Но это было бы смелое решение с плохо ограниченным радиусом поражения. Вставить один NOP в конкретный бинарный участок было менее изящно, зато значительно безопаснее в контексте дедлайна.

Для русскоязычной ИТ-аудитории здесь сразу несколько практических выводов. Первый: баги, которые исчезают под наблюдением, не мистика, а обычный побочный эффект того, как инструменты меняют среду исполнения, тайминги и раскладку кода. Второй: заморозка toolchain перед релизом существует не из бюрократической любви к запретам, а потому что даже полезное обновление компилятора способно перегенерировать слишком много машинного кода сразу. Третий: аппаратные errata никуда не делись, просто сегодня они чаще скрыты под слоями виртуализации, JIT, драйверов и микрокода. Но если продукт работает на большом парке разнородного железа, рано или поздно кто-то в команде снова упрется в дефект, который воспроизводится «только у части пользователей и только по четвергам».

Есть и более широкий организационный смысл. Такие истории хорошо объясняют, почему сильные команды сохраняют у себя не только прикладную экспертизу, но и людей, способных читать дизассемблированный код, разбираться в errata производителей и принимать неприятные, но точные релизные решения. Когда индустрия слишком увлекается скоростью поставки, платформенной магией и очередным слоем абстракций, она иногда забывает простую вещь: внизу все еще исполняются инструкции на конкретном процессоре. И если одна лишняя инструкция способна сломать продукт, то одна лишняя NOP-команда иногда может его спасти.

Сюжет про сбой Word 97 поэтому выглядит не музейным экспонатом, а вполне живым напоминанием: чем сложнее становятся компиляторы, процессоры и среды выполнения, тем ценнее умение отличать системную проблему от локальной и чинить ее минимальным движением. В 1997 году таким движением оказался один NOP. В 2026-м это по-прежнему звучит как хороший аргумент против инженерного самодовольства.

Поделиться: Telegram X LinkedIn