Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.90/20: Рейтинг темы: голосов - 20, средняя оценка - 4.90
Виктор_Сен
33 / 26 / 2
Регистрация: 01.08.2011
Сообщений: 176
1

СИ++ и контроль переполнения

10.11.2011, 13:03. Просмотров 3608. Ответов 20
Метки нет (Все метки)

Можно ли как-нибудь в VS включить контроль переполнения при математических вычислениях? Чтоб, например, возникало исключение. Или это можно сделать только средствами ассемблера путём контроля флагов?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
10.11.2011, 13:03
Ответы с готовыми решениями:

Переполнения безопастны?
Насколько безопасна строчка: for(unsigned int b(UINT_MAX); ++b != UINT_MAX;) ...

Отслеживание переполнения
Привет. Подскажите пожалуйста как ловить переполнение переменной типа size_t (...

Защита от переполнения
Ребят помоги создать защиту от переполнения через функцию scanf_s и убрать...

Флаг переполнения
Доброго времени суток! Подскажите, как проверить какую-либо определенную...

Ошибка переполнения массива
Здравствуйте. Задача легкая,нужно создать массив из 1000000 элементов,и найти...

20
-=ЮрА=-
Заблокирован
Автор FAQ
10.11.2011, 13:39 2
Думаю можно и проще чем заюзывать asm приведу пример
C
1
2
3
4
5
6
7
8
int val;
long param;
do
{
     cin>>param;
}
while(INT_MAX < param);
val = (int)param;
0
kazak
3058 / 2379 / 255
Регистрация: 11.03.2009
Сообщений: 5,438
Завершенные тесты: 1
10.11.2011, 14:32 3
-=ЮрА=-, как это может помочь при контроле выполнения математических операций?
0
talis
793 / 545 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
10.11.2011, 14:34 4
Виктор_Сен, как вариант - перегрузить операторы для нужных вам типов, и в них выполнять проверки.
1
LosAngeles
Заблокирован
10.11.2011, 14:36 5
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
 
using namespace std;
 
int main()
{
    int x = 10000, y = 100000, result;
    
    cout << "Input two operands!" << endl;
    cin >> x >> y;
     
    result = x*y;
    __asm__ __volatile__ ("jno label");
    cout << "Overflow detected!" << endl; 
    __asm__ ("label:");
    cout << result << endl;
    return 0;
}
в ВС еще проще, он позволяет ассемблерным вставкам обращаться к меткам за пределами ассемблерной вставки, в гсс вроде такой трюк не прокатывает
2
Петррр
10.11.2011, 14:39
  #6

Не по теме:

Еще можно бросить плюсы, взять C#. Там есть checked

0
-=ЮрА=-
Заблокирован
Автор FAQ
10.11.2011, 14:45 7
Цитата Сообщение от kazak Посмотреть сообщение
-=ЮрА=-, как это может помочь при контроле выполнения математических операций?
- очень просто например нам нужны целочисленные значения, выполняем расчёты с ними например считаем сумму ряда в double sum, а затем смотрим если величина суммы превосходит INT_MAX то выдаём сообщение о переполнении, если же нет то делаем int val = (int)sum Вобщем в стандартных типах можно реализовать всё даже для float лишь бы желание было...
константа INT_MAX и многие другие прописаны в limits.h

Добавлено через 5 минут

Не по теме:

LosAngeles, задание предполагает альтарнативные асму варианты...

Цитата Сообщение от Виктор_Сен Посмотреть сообщение
Можно ли как-нибудь в VS включить контроль переполнения при математических вычислениях?Или это можно сделать только средствами ассемблера путём контроля флагов?
Как я понял с асемблеровским вариантом ТС знаком

0
talis
793 / 545 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
10.11.2011, 14:48 8
-=ЮрА=-, а если нужно контролировать переполнение в unsigned long long или long long double?
0
Net_Wanderer
235 / 208 / 29
Регистрация: 08.06.2011
Сообщений: 467
10.11.2011, 14:49 9
Цитата Сообщение от talis Посмотреть сообщение
Виктор_Сен, как вариант - перегрузить операторы для нужных вам типов, и в них выполнять проверки.
Насколько я помню, нельзя перегружать операторы для базовых типов данных.
2
talis
793 / 545 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
10.11.2011, 15:00 10
Лучший ответ Сообщение было отмечено как решение

Решение

Net_Wanderer, да, поторопился. Извините.

Добавлено через 8 минут
А если сделать шаблонную обёртку, то можно:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
#include <stdexcept>
 
template< typename _Tp >
struct var
{
    _Tp data;
 
    var( const _Tp d ) : data(d) {};
 
    var<_Tp> & operator+=( const var<_Tp> &d )
    {
        data += d;
        return *this;
    }
 
    _Tp & operator*()
    {
        return data;
    }
 
    operator _Tp()
    {
        return data;
    }
};
 
template< typename _Tp >
var< _Tp > & operator+( const var< _Tp > &a, const var< _Tp > &b )
{
    var< _Tp > v( a );
    v += b;
    return v;
}
 
typedef var<int> int_v;
 
int main( )
{
    int_v a = 50;
 
    std::cout << a << '\n';
 
    a = 12 + 8;
 
    std::cout << a << '\n';
 
    return 0;
}
3
silent_1991
Эксперт С++
5009 / 3069 / 270
Регистрация: 11.11.2009
Сообщений: 7,043
Завершенные тесты: 1
10.11.2011, 21:42 11
talis, разумеется, ведь шаблонная обёртка не подпадает под понятие "базовый тип"
0
-=ЮрА=-
Заблокирован
Автор FAQ
11.11.2011, 10:47 12
Цитата Сообщение от Виктор_Сен Посмотреть сообщение
Можно ли как-нибудь в VS включить контроль переполнения при математических вычислениях? Чтоб, например, возникало исключение.
- ниже простой код не требующий введения классов и преобразований к старшему типу данных, я написал лишь ветвь для сложения, но завершить алгоритм труда не составит(остаётся заполнить лишь 3 case в множественном выборе)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <iostream>
#include <conio.h>
using namespace std;
 
int main()
{
    char ch;
    bool bFlag;
    int val1, val2;
    char choperator;
    do
    {
        cout<<"\tThis algorithm checking limits in algebraic operations\n";
        cout<<"Enter equation val1 operator val2, val1(2) - INT operator : + - / *\n";
        cout<<"Example 5 + 6\n";
        cout<<" "<<INT_MAX<<" - maximum INT value\n";
        cout<<INT_MIN<<" - minimum INT value\n>";
        bFlag= true;//Çäåñü ГЅГІГ® ГґГ«Г*ГЈ äëÿ ââîäГ*
        val1 = 0;val2 = 0;
        while((ch = getchar()) != '\n')
        {
            if(isdigit(ch))
            {
                if(bFlag)
                {
                    if(INT_MAX/10 < val1)
                        cout<<"You trying enter val1 accedes INT_MAX\n";
                    else
                    {
                        val1 *= 10;
                        val1 += ((int)ch - '0');
                    }
                }
                else
                {
                    if(INT_MAX/10 < val2)
                        cout<<"You trying enter val2 accedes INT_MAX\n";
                    else
                    {
                        val2 *= 10;
                        val2 += ((int)ch - '0');
                    }
                }
            }
            else
            {
                if(!isspace(ch))
                    choperator = ch;
                if(bFlag)
                    bFlag = false;
            }
        }
        
        cout<<"\tCalculation of equation\n";
        cout<<val1<<" "<<choperator<<" "<<val2<<" = ";
        bFlag = true;//Òåïåðü ГЅГІГ® óæå ГґГ«Г*ГЈ äëÿ Г¬Г*òîïåðГ*öèé
        switch(choperator)
        {
        case '+' :
            if(0 <= val1)
            {
                if(INT_MAX - val1 < val2)
                    bFlag = false;
            }
            else
            {
                if(val2 < 0)
                if(val2 < INT_MIN - val1)
                    bFlag = false;
            }
            if(bFlag)
                cout<<(val1 + val2)<<endl;
            else
                cout<<"Result of val1 + val2 out of [-INT_MIN;INT_MAX]\n";
            break;
        case '-' :
            break;
        case '*' :
            break;
        case '/' :
            break;
        default:
            cout<<"You enter unsupported operator\n";
            break;
        }
        cout<<"Press Y-key for new input\n";
    }
    while(toupper(getch()) == 'Y');
    return 0;
}
0
Миниатюры
СИ++ и контроль переполнения  
-=ЮрА=-
Заблокирован
Автор FAQ
11.11.2011, 10:49 13
PS:
Цитата Сообщение от talis Посмотреть сообщение
-=ЮрА=-, а если нужно контролировать переполнение в unsigned long long или long long double?
- руководствуясь приведенной мной логикой можно контролировать и эти типы...
0
talis
793 / 545 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
11.11.2011, 12:18 14
-=ЮрА=-, без введения обёрток математическая формула, реализованная вашим способом, станет абсолютно нечитаемой.
0
-=ЮрА=-
Заблокирован
Автор FAQ
11.11.2011, 12:57 15
Цитата Сообщение от talis Посмотреть сообщение
реализованная вашим способом, станет абсолютно нечитаемой.
- что под этим подразумевалось, чем это не читаемое выражение?
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
cout<<(val1 + val2)<<endl;
Алгоритм просто не даст сложить неправильно и всё
Кстати у вас же ещё ветвь проверки значения нужно здесь дописать
Цитата Сообщение от talis Посмотреть сообщение
var<_Tp> & operator+=( const var<_Tp> &d )
* * {
* * * * data += d;
* * * * return *this;
* * }
, причём от моих условных операторов она абсолютно ничем отличаться не будет. Кроме того мой код потянет даже самый самый начинающий, обвёртка уже предполагает некоторых знаний

Не по теме:

В заключение вот тест Вашего алгоритма

C++
1
2
3
4
5
6
7
8
9
int main( )
{
    int iMAX = INT_MAX;
    int_v a = iMAX;
    std::cout << a << '\n';
    a = iMAX + 8;
    std::cout << a << '\n';
    return 0;
}
- я пока не пишу что он не реализует предполагаемую задачу, т.к. возможно вы именно как обворачивать без обработки исключений представить хотели...

0
Миниатюры
СИ++ и контроль переполнения  
talis
793 / 545 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
11.11.2011, 13:03 16
-=ЮрА=-, если вы внимательно посмотрите код обёртки, то увидите, что я не включал туда никакого контроля. Реально внутри обёртки должен быть код, подобный вашему (лучше, конечно, ассемблерный вариант). А использование её в программе сведётся как раз к выражениям вида

C++
1
double_v dub = a + 15 * sqrt(b) + c;
Весь этот код проверки будет внутри обёртки и код вычислений станет читабельным. В вашем варианте всё это дело придётся писать перед каждой операцией, причём составные выражения вроде того, которое я привёл выше, будет невозможно сделать.
0
-=ЮрА=-
11.11.2011, 13:25
  #17

Не по теме:

Цитата Сообщение от talis Посмотреть сообщение
сли вы внимательно посмотрите код обёртки, то увидите, что я не включал туда никакого контроля
- я поэтому и писал.
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
возможно вы именно как обворачивать без обработки исключений представить хотели
, Замечание сделал на случай вдруг ТС ещё не имеет достаточного багажа знаний и напрямую попытается использовать ваш код, это не претензия к вам была:pardon:На счёт остального соглашусь, я делал под начинающего, у вас как должно быть в программе уже набившего руку программиста;)

1
LosAngeles
Заблокирован
11.11.2011, 14:30 18
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/**
    OVERFLOW_ASSERT(label) macro
        throw exception if OF == 1 || CF == 1
    params:
        label - name of label for compiler, so avoid of using the same name twice!
    return:
        code for MSVC or code for g++
*/
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
    #define OVERFLOW_ASSERT(label) \
    __asm { JNO label }; \
    __asm { JNC label }; \
    throw std::overflow_error("This is SPARTAAAA!"); \
label:
#elif defined(__GNUG__)
    #define OVERFLOW_ASSERT(label) \
    __asm__ ("JNO label" \
            "JNC label"); \
    throw std::overflow_error("This is SPARTAAAA!"); \
    __asm__ ("label:");
#endif
 
 
 
template< typename _Tp >
struct var
{
    _Tp data;
 
    var( const _Tp d ) : data(d) {};
 
    var<_Tp> & operator+=( const var<_Tp> d )
    {
        data += d.data;
        OVERFLOW_ASSERT(addition)
        return *this;
    }
 
    var<_Tp> & operator*=( const var<_Tp> d )
    {
        
        data *= d.data;
        OVERFLOW_ASSERT(multiplication)
        return *this;
    }
 
    _Tp & operator*()
    {
        return data;
    }
 
    operator _Tp()
    {
        return data;
    }
};
Добавлено через 9 минут
talis, кстати говоря в чём смысл 44 строки в твоём листинге? там же built-in оператор используется, и как бы нельзя проверить переполнение, а то я уже было обрадовался
1
talis
793 / 545 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
11.11.2011, 14:41 19
LosAngeles, да, спасибо. Должно быть так:

C++
1
a = int_v(12) + 8;
0
Evg
Эксперт CАвтор FAQ
19288 / 7147 / 528
Регистрация: 30.03.2009
Сообщений: 19,997
Записей в блоге: 30
11.11.2011, 15:01 20
Лучший ответ Сообщение было отмечено как решение

Решение

Цитата Сообщение от Виктор_Сен Посмотреть сообщение
Можно ли как-нибудь в VS включить контроль переполнения при математических вычислениях? Чтоб, например, возникало исключение. Или это можно сделать только средствами ассемблера путём контроля флагов?
О каких переполнениях идёт речь?

Если речь идёт о целочисленных переполнениях, то в современных процессорах вроде бы нет возможности сделать так, чтобы возникало прерывание при переполнении. Возможно только пощупать соответствующие целочисленные флаги непосредственно после выполнения операции, а потому нужно весь кусок (который вычисляет операцию и вызывает прерывание) полностью писать на ассемблере

Если же речь идёт о плавающих вычислениях, то оно как правило процессорами поддерживается, потому что прерывания требуются по стандарту ieee-754. Для этого есть стандартные функции типа http://linux.die.net/man/3/feenableexcept но они, насколько я знаю, входят в стандарт Си99
4
11.11.2011, 15:01
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.11.2011, 15:01

Как отловить переполнения?
Есть проект dll, в в нём экспортируемая функция, возвращающая BOOL, требуется...

Ошибка переполнения буфера
При первом запуске програма работает, после второго появляеться ошибка...

Проверка переполнения double
Добрый день! Подскажите пожалуйста, где можно почитать теорию. Нужно решить...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru