Как взорвать ракету одной переменной
easy

Как взорвать ракету одной переменной

Краткий мастер-класс по правильному объявлению типов данных.

Что произошло

Ошибки в коде бывают у всех, но их последствия всегда разные. Одно дело — ошибиться в программе для шагомера и потерять 500 шагов, и другое — лишиться полумиллиарда долларов.

Эта история произошла в 1996 году, когда Европейское космическое агентство потеряло космическую ракету-носитель Ariane-5 из-за неправильно объявленной переменной. Через 40 секунд после старта ракета взорвалась в воздухе, полностью уничтожив четыре спутника, которые нужно было вывести на орбиту.

Когда комиссия начала расследование, она выяснила, что во всём виновата одна переменная, которая не могла принимать значение больше, чем 32 767. Этого оказалось достаточно, чтобы всё вышло из-под контроля.

Ракета-носитель Ariane-5, фото из Википедии

В чём причина

В летательном аппарате был модуль, который отвечал за ориентировку в пространстве, — инерционная система ориентировки, ИСО. Европейцы ставили этот элемент на все ракеты, допиливая его под разные задачи. Ariane-5 достался модуль от Ariane-4. Думали, что раз он прекрасно показал себя на предыдущем аппарате, то и на новом тоже всё заработает.

Ракета Ariane-4 летала не так быстро, как Ariane-5, и модуль мог спокойно посчитать всё, что ему было нужно, используя переменные в диапазоне от −32 768 до 32 767. Причём этот промежуток был с запасом: в реальности такие числа на Ariane-4 не использовались.

Но Ariane-5 летала намного быстрее. Переменные очень скоро достигли своего максимального значения и вызвали сбой. Включился резервный модуль, но в нём стоял точно такой же софт от старой ракеты, который сделал всё то же самое: быстро достиг потолка в переменной и тоже вызвал сбой. Ariane-5 продолжала ускоряться.

Через 40 секунд после старта ракета набрала такую высокую скорость, что аэродинамическая нагрузка стала критической: обшивка начала разрушаться, стартовые двигатели отделились, и аппарат взорвался.

Память у компьютеров не резиновая. Когда мы пишем программу и нужно в ней что-то запомнить, мы говорим компьютеру: «Выдели нам память для такой-то информации».

Есть языки программирования, где место для данных выделяется автоматически. Например, в JavaScript просто говоришь: «Вот новая переменная, положи в неё вот это», — и система сама определит, сколько на эту информацию нужно памяти. Есть языки, где необходимо чётко сказать, какого типа переменную следует создать. Например, в языке C:

int speed;
speed = 99;

Int означает integer, то есть целое число. На целое число выделяется сколько-то памяти, в зависимости от языка. Чтобы не погружаться в битность и сложности двоичного счисления, представьте такую ситуацию.

Вы делаете инвентаризацию товаров на складе. По каждой позиции вы заполняете форму, в которой есть поле «Порядковый номер». В этой графе три пустых клетки, которые вы можете заполнить цифрами от 0 до 9. Если начинать с товара 001, то максимальное количество позиций, которое вы можете посчитать с помощью этих трёх клеток, — 999.

[0] [0] [1]

[0] [0] [2]

[0] [0] [3]

...

[9] [9] [9]

Если у вас на складе лежит более 999 товаров, вам потребуется какая-то другая форма, в которой будет уже не три, а четыре клетки. Или можно объявить программный сбой и уйти на обед.

Вот это и произошло с ракетой:

  1. Ракете дали, грубо говоря, 16 клеток, чтобы записать какой-то параметр скорости.
  2. Максимальное число, которое можно было записать на компьютере, используя 16 компьютерных клеток, — 65 535.
  3. Если нам нужны числа с плюсами и минусами, то мы получаем диапазон значений от −32 768 до +32 767.
  4. Всё, что выходит за рамки этого промежутка, компьютер уже не может записать — так же, как мы не можем внести в три клетки число более 999.
  5. Программе нужно было записать число больше, чем 32 767. А клеток не хватает!
  6. Дальше вы знаете.

Вот так одна строка кода может пустить на ветер кучу денег и стать одной из самых дорогих ошибок в истории программирования. А вот та самая строка:

P_M_DERIVE(T_ALG.E_BH) := UC_16S_EN_16NS (TDB.T_ENTIER_16S

                                  ((1.0/C_M_LSB_BH) *

                                  G_M_INFO_DERIVE(T_ALG.E_BH)))

Обложка:

Даня Берковский

Корректор:

Ирина Михеева

Вёрстка:

Маша Климентьева

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

Старая, но интересная задача про то, как выполнить невыполнимое условие.

hard
Как сделать свой сайт за 10 минут без программирования
Как сделать свой сайт за 10 минут без программирования

Для некоторых это становится источником постоянного дохода, если подойти к процессу с умом.

easy
Захватят ли нанороботы мир?
Захватят ли нанороботы мир?

Моделируем ход техногенной катастрофы с помощью простого уравнения.

easy
Задача: сто программистов и повышение или увольнение для всех
Задача: сто программистов и повышение или увольнение для всех

Все либо выиграют, либо проиграют

easy
Задача имени Якубовича: три шкатулки с деньгами
Задача имени Якубовича: три шкатулки с деньгами

Интуиция обманет вас в этой задаче. Попробуйте лучше теорию вероятностей, это легко.

hard
Вы не сможете решить эту задачу про повышение и пароль
Вы не сможете решить эту задачу про повышение и пароль

Задача дьявольски сложная, но решение есть

hard
Как найти кота?
Как найти кота?

Есть 5 коробок и в одной из них он сидит.

easy
Крутейшие задачи на комбинаторику
Крутейшие задачи на комбинаторику

Комбинаторика и поиск наилучшего решения для всех.

medium
Сборник задач на логику для тренировки мозга
Сборник задач на логику для тренировки мозга

Для любой компании

easy
easy