Переполнение в программировании и математике¶
Переполнение (англ. overflow) — явление в вычислительной технике и математике, при котором результат арифметической операции или преобразования данных превышает максимально допустимое значение для используемого формата представления чисел. В зависимости от контекста переполнение может приводить к ошибкам вычислений, некорректной работе программ или, напротив, к штатному поведению в рамках модулярной арифметики.
¶Переполнение целочисленного типа
Целочисленное переполнение возникает, когда результат операции выходит за границы диапазона значений типа данных. Например, для 8-битного беззнакового целого (диапазон 0–255) сложение 255 + 1 даёт 0, так как старший бит теряется. Для знаковых типов поведение зависит от реализации и языка программирования: в языке C переполнение знаковых целых является неопределённым поведением (undefined behavior), тогда как в Java и C# оно определено и приводит к «заворачиванию» (wraparound) по модулю 2^n.
Различают переполнение вверх (результат больше максимума) и переполнение вниз (англ. underflow), когда результат меньше минимума. Целочисленное переполнение часто становится источником уязвимостей в программном обеспечении: классические примеры — ошибки в вычислении размера буфера, приводящие к переполнению буфера, или некорректная проверка границ массивов.
¶Переполнение с плавающей запятой
В числах с плавающей запятой (стандарт IEEE 754) переполнение происходит, когда порядок результата превышает максимально представимый. При этом результат обычно устанавливается в бесконечность (Infinity) или в специальное значение NaN, если операция не определена. Переполнение вниз (underflow) возникает, когда результат настолько мал по абсолютной величине, что нормализовать его невозможно; тогда число теряет точность и может стать денормализованным или нулём. В отличие от целочисленного переполнения, поведение при переполнении с плавающей запятой строго регламентировано стандартом и предсказуемо.
¶Переполнение стека
Переполнение стека (stack overflow) — особый случай, связанный не с арифметикой, а с исчерпанием области памяти, выделенной под стек вызовов. Возникает при чрезмерно глубокой рекурсии, бесконечных циклах с вложенными вызовами функций или при размещении в стеке слишком больших локальных массивов. При переполнении стека программа обычно аварийно завершается с ошибкой сегментации (segmentation fault) или исключением. Классический пример — рекурсивная функция без условия выхода. Переполнение стека также может быть использовано злоумышленниками для атак, если в стек попадают данные, управляющие адресом возврата (эксплойты переполнения буфера в стеке).
¶Переполнение буфера
Переполнение буфера (buffer overflow) — тип уязвимости, при котором данные записываются за границы выделенного участка памяти (буфера). В языках без автоматического контроля границ (C, C++) некорректная работа со строками или массивами может привести к перезаписи соседних областей памяти, включая адреса возврата и указатели. Это одна из самых распространённых причин удалённого выполнения кода. Для защиты применяются методы: проверка границ, канарейки в стеке, ASLR (рандомизация адресного пространства), безопасные библиотеки функций (например, strlcpy вместо strcpy).
¶Переполнение в модулярной арифметике
В некоторых областях переполнение не считается ошибкой. В криптографии и теории колец часто используется арифметика по модулю 2^n, где переполнение естественно и обратимо. Например, в хеш-функциях и генераторах псевдослучайных чисел сложение с переносом и игнорированием старших битов является штатным режимом. Аналогично, в цифровой обработке сигналов переполнение сумматоров иногда допускается при условии использования насыщения (saturation) — ограничения результата максимальным или минимальным значением.
¶Способы обнаружения и предотвращения
Для борьбы с переполнением применяются следующие подходы:
- Проверка перед операцией: сравнение операндов с границами до выполнения арифметического действия.
- Расширение типа: выполнение операции в типе большей разрядности (например,
longвместоint) с последующей проверкой. - Встроенные функции компиляторов: в GCC и Clang доступны
__builtin_add_overflowи аналоги, возвращающие признак переполнения. - Аппаратная поддержка: флаг переноса (carry flag) в процессорах, исключения при переполнении в некоторых архитектурах (например, MIPS).
- Языковые средства: в Rust переполнение в отладочной сборке вызывает панику, в release-сборке — заворачивание; в Python целые числа произвольной точности не переполняются.
- Статический анализ: инструменты вроде Coverity, PVS-Studio и санитайзеров (UBSan) выявляют потенциальные переполнения на этапе компиляции и тестирования.
¶Переполнение в математике
В классической математике понятие переполнения отсутствует, поскольку числа не ограничены разрядностью. Однако при численных расчётах на компьютере переполнение может возникать в промежуточных вычислениях даже тогда, когда конечный результат корректен. Например, вычисление sqrt(x^2 + y^2) при больших x и y вызывает переполнение квадрата, хотя гипотенуза представима. Для таких случаев применяются устойчивые алгоритмы (например, масштабирование аргументов).
¶Известные инциденты
Переполнение неоднократно приводило к реальным авариям. В 1996 году взрыв ракеты «Ариан-5» произошёл из-за переполнения 64-битного числа с плавающей запятой при преобразовании в 16-битное целое. В 2015 году переполнение в системе управления самолётом Boeing 787 могло привести к полной потере питания генераторов. Ошибка переполнения в программном обеспечении космического аппарата «Фобос-Грунт» в 2011 году стала одной из причин неудачного запуска.
¶См. также
- Арифметика с плавающей запятой
- Целочисленная арифметика
- Уязвимость программного обеспечения
¶Источники
- Брайант Р., О’Халларон Д. «Компьютерные системы: архитектура и программирование».
- Танейбаум Э., Остин Т. «Архитектура компьютера».
- Стандарт IEEE 754-2019.
- Документация GCC по встроенным функциям проверки переполнения.
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →

