The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  ВХОД  слежка  RSS
"Корректная проверка на целочисленное переполнение"
Вариант для распечатки  
Пред. тема | След. тема 
Форумы Программирование под UNIX (Public)
Изначальное сообщение [Проследить за развитием треда]

"Корректная проверка на целочисленное переполнение"  
Сообщение от dimus (??) on 17-Фев-06, 13:15 
В последнее время стало появляться много сообщений об обнаружении в разных программах ошибок, связанных с целочисленным переполнением.
Допустим у нас есть код, где одна переменная время от времени увеличивается на некоторое заранее неизвестное значение. Например так:

unsigned int counter;

void accounting( unsigned int delta )
{
   counter = counter + delta;
}

В определенный момент может быть достигнуто такое состояние, когда после прибавления очередной дельты у нас будет переполнение. Я придумал такой путь решения проблемы:
void accounting2( unsigned int delta )
{
   if( counter < (counter + delta) )
   {
      counter = counter + delta;
   }
   else
   {
      printf("Overflow detected\n");
   }
}

Однако этот способ аппаратно зависимый и не лишен недостатков: он не будет работать, если при переполнении не происходит циклического перехода в регистре. (т.е. допустим у нас есть восьмиразрядный регистр А, содержащий число 0xFE. Если добавить к нему 0x1, то мы получим 0xFF, а если добавить 0x3, то мы получим переполнение, и в регистре у нас будет 0x1. По крайней мере это характерно для платформы ИНТЕЛ)

Вопрос: как правильно отслеживать факт целочисленного переполнения?

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

 Оглавление

Сообщения по теме [Сортировка по времени, UBB]


1. "Корректная проверка на целочисленное переполнение"  
Сообщение от СергейК email(??) on 17-Фев-06, 15:32 
Для signed int подходит следующее

#define SAMESIGN(a,b)   (((a) < 0) == ((b) < 0))
void accounting2( int delta )
{
   int counter1 = counter + delta
   if (SAMESIGN(counter, delta) && !SAMESIGN(counter, counter1))
   {
      fprintf(stderr,"Overflow detected\n");
   }
   return counter1;
}

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

2. "Корректная проверка на целочисленное переполнение"  
Сообщение от sas email(??) on 18-Фев-06, 11:44 
>В последнее время стало появляться много сообщений об обнаружении в разных программах
>ошибок, связанных с целочисленным переполнением.
>Допустим у нас есть код, где одна переменная время от времени увеличивается
>на некоторое заранее неизвестное значение. Например так:
>
>unsigned int counter;
>
>void accounting( unsigned int delta )
>{
>   counter = counter + delta;
>}
>
>В определенный момент может быть достигнуто такое состояние, когда после прибавления очередной
>дельты у нас будет переполнение. Я придумал такой путь решения проблемы:
>
>void accounting2( unsigned int delta )
>{
>   if( counter < (counter + delta) )
>   {
>      counter = counter + delta;
>   }
>   else
>   {
>      printf("Overflow detected\n");
>   }
>}
>
>Однако этот способ аппаратно зависимый и не лишен недостатков: он не будет
>работать, если при переполнении не происходит циклического перехода в регистре. (т.е.
>допустим у нас есть восьмиразрядный регистр А, содержащий число 0xFE. Если
>добавить к нему 0x1, то мы получим 0xFF, а если добавить
>0x3, то мы получим переполнение, и в регистре у нас будет
>0x1. По крайней мере это характерно для платформы ИНТЕЛ)
>
>Вопрос: как правильно отслеживать факт целочисленного переполнения?

if ( counter > ~delta )
   fprintf( stderr, "Overflow!!!\n" );

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

3. "Корректная проверка на целочисленное переполнение"  
Сообщение от sas email(??) on 18-Фев-06, 11:47 
>>В последнее время стало появляться много сообщений об обнаружении в разных программах
>>ошибок, связанных с целочисленным переполнением.
>>Допустим у нас есть код, где одна переменная время от времени увеличивается
>>на некоторое заранее неизвестное значение. Например так:
>>
>>unsigned int counter;
>>
>>void accounting( unsigned int delta )
>>{
>>   counter = counter + delta;
>>}
>>
>>В определенный момент может быть достигнуто такое состояние, когда после прибавления очередной
>>дельты у нас будет переполнение. Я придумал такой путь решения проблемы:
>>
>>void accounting2( unsigned int delta )
>>{
>>   if( counter < (counter + delta) )
>>   {
>>      counter = counter + delta;
>>   }
>>   else
>>   {
>>      printf("Overflow detected\n");
>>   }
>>}
>>
>>Однако этот способ аппаратно зависимый и не лишен недостатков: он не будет
>>работать, если при переполнении не происходит циклического перехода в регистре. (т.е.
>>допустим у нас есть восьмиразрядный регистр А, содержащий число 0xFE. Если
>>добавить к нему 0x1, то мы получим 0xFF, а если добавить
>>0x3, то мы получим переполнение, и в регистре у нас будет
>>0x1. По крайней мере это характерно для платформы ИНТЕЛ)
>>
>>Вопрос: как правильно отслеживать факт целочисленного переполнения?
>
if ( counter > ~delta ) fprintf( stderr, "Overflow!!!\n" );
Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

4. "Корректная проверка на целочисленное переполнение"  
Сообщение от dimus (??) on 21-Фев-06, 08:21 
>if ( counter > ~delta ) fprintf( stderr, "Overflow!!!\n" );

Интересно и Красиво!
Большое вам спасибо. И этот метод вроде как должен переноситься на любые архитектуры.

Интересно, а почему не сделали набор таких функций и не включили в стандартную библиотеку - вещь то очень нужная. Что-то типа этого:
int   safe_add_uint32( uint32_t val1, uint32_t val2, uint32_t* result );

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

5. "Корректная проверка на целочисленное переполнение"  
Сообщение от dimus (??) on 22-Фев-06, 15:07 
>Интересно, а почему не сделали набор таких функций и не включили в
>стандартную библиотеку - вещь то очень нужная. Что-то типа этого:
>int   safe_add_uint32( uint32_t val1, uint32_t val2, uint32_t* result );

Я решил сделать себе ряд таких функций. Для uint32_t и uint64_t все заработало прекрасно, и я ободренный этим, решил сделать также функции для uint8_t и uint16_t. Каково же было мое удивление и недоумение, когда эти функции незаработали!
Расследование выявило, что компилятор (gcc (GCC) 3.3.4) как-то странно рожает код для оператора if: вместо того, чтобы использовать cmpb или cmpw (для uint16_t), он использовал cmpl, и в результате функция не работает. Помогло приведение типов. Вот рабочий код:

//-------------------------------------------------------------------
// Безопасное сложение двух чисел с контролем переполнения
// val1 - первое число
// val2 - второе число
// res - указатель на переменную, в которую будет записан
// результат. В случае, если было зафиксированно переполнение,
// эта переменная останется в неизменном виде.
// Возвращаемое значение: 1 в случае успеха, 0 при переполнении
int     safe_add_uint8( uint8_t val1, uint8_t val2, uint8_t* res )
{
        int     result  = 0;

        if( (uint8_t)val1 <= (uint8_t)~val2 )
        {
                *res = val1 + val2;
                result = 1;
        }

        return  result;
}
//-------------------------------------------------------------------

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

6. "Корректная проверка на целочисленное переполнение"  
Сообщение от tilde on 22-Фев-06, 15:45 
Вообще-то gcc действует строго по стандарту. Сложение для char и short выполняется в типе int.
Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

Архив | Удалить

Индекс форумов | Темы | Пред. тема | След. тема
Оцените тред (1=ужас, 5=супер)? [ 1 | 2 | 3 | 4 | 5 ] [Рекомендовать для помещения в FAQ]




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру