Как обнаружить переполнение в C ++? - PullRequest
4 голосов
/ 22 сентября 2009

Мне просто интересно, есть ли какой-нибудь удобный способ определить, происходит ли переполнение с какой-либо переменной любого типа данных по умолчанию, используемой в программе C ++ во время выполнения? Под удобством я подразумеваю, что нет необходимости писать код для каждой переменной, если она находится в диапазоне своего типа данных каждый раз, когда ее значение изменяется. Или, если это невозможно, как бы вы это сделали?

Например,

float f1=FLT_MAX+1;
cout << f1 << endl;

не выдает никаких ошибок или предупреждений ни при компиляции с "gcc -W -Wall", ни при запуске.

Спасибо и всего наилучшего!

Ответы [ 6 ]

6 голосов
/ 22 сентября 2009

Рассмотрите возможность использования , повышающего числовое преобразование , которое дает вам negative_overflow и positive_overflow исключения ( примеров ).

4 голосов
/ 22 сентября 2009

Ваш пример фактически не переполняется в среде с плавающей запятой по умолчанию в системе, совместимой с IEEE-754.

В такой системе, где float - это 32-разрядная двоичная с плавающей запятой, FLT_MAX - 0x1.fffffep127 в шестнадцатеричной записи с плавающей запятой C99. Запись в виде целого числа в шестнадцатеричном виде, это выглядит так:

0xffffff00000000000000000000000000

Добавление одного (без округления, как если бы значения были произвольными целыми числами точности), дает:

0xffffff00000000000000000000000001

Но в среде с плавающей точкой по умолчанию в системе, совместимой с IEEE-754, любое значение находится в диапазоне

0xfffffe80000000000000000000000000

и

0xffffff80000000000000000000000000

(включая указанное вами значение) округляется до FLT_MAX. Переполнения не происходит.

Ситуация усугубляется тем, что ваше выражение (FLT_MAX + 1), вероятно, будет оценено во время компиляции, а не во время выполнения, так как оно не имеет побочных эффектов, видимых для вашей программы.

2 голосов
/ 22 сентября 2009

В старые времена, когда я разрабатывал C ++ (199x), мы использовали инструмент под названием Purify. Тогда это был инструмент, который инструментировал объектный код и регистрировал все «плохое» во время тестового прогона. Я сделал быстрый Google, и я не совсем уверен, если он все еще существует.

Насколько я знаю, в настоящее время существует несколько инструментов с открытым исходным кодом, которые делают более или менее то же самое. Оформление электроизгороди и валгринда.

2 голосов
/ 22 сентября 2009

В ситуациях, когда мне нужно обнаружить переполнение, я использую SafeInt<T>. Это кроссплатформенное решение, которое выдает исключение в ситуациях переполнения.

SafeInt<float> f1 = FLT_MAX;
f1 += 1; // throws

Доступно на codeplex

1 голос
/ 25 сентября 2009

Информация, которая может быть полезна по этому вопросу:

Глава 5 «Безопасного кодирования на C и C ++» от Seacord

http://www.informit.com/content/images/0321335724/samplechapter/seacord_ch05.pdf

Классы SafeInt для C ++

http://blogs.msdn.com/david_leblanc/archive/2008/09/30/safeint-3-on-codeplex.aspx http://www.codeplex.com/SafeInt

Библиотека IntSafe для C:

http://blogs.msdn.com/michael_howard/archive/2006/02/02/523392.aspx

Источник: Как обнаружить целочисленное переполнение?

0 голосов
/ 29 ноября 2014

Clang обеспечивает -fsanitize=signed-integer-overflow и -fsanitize=unsigned-integer-overflow.

http://clang.llvm.org/docs/UsersManual.html#controlling-code-generation

...