Форум программистов, компьютерный форум CyberForum.ru

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

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 22, средняя оценка - 4.59
Виктор_Сен
 Аватар для Виктор_Сен
29 / 22 / 1
Регистрация: 01.08.2011
Сообщений: 176
10.11.2011, 13:03     СИ++ и контроль переполнения #1
Можно ли как-нибудь в VS включить контроль переполнения при математических вычислениях? Чтоб, например, возникало исключение. Или это можно сделать только средствами ассемблера путём контроля флагов?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
10.11.2011, 13:03     СИ++ и контроль переполнения
Посмотрите здесь:

C++ проверка переполнения double
39+ (-39) будет ли установлен флаг переполнения? C++
C++ Ошибка переполнения буфера
Защита от переполнения C++
C++ Ошибка переполнения массива
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
-=ЮрА=-
Заблокирован
Автор 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;
kazak
 Аватар для kazak
3029 / 2350 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
10.11.2011, 14:32     СИ++ и контроль переполнения #3
-=ЮрА=-, как это может помочь при контроле выполнения математических операций?
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
10.11.2011, 14:34     СИ++ и контроль переполнения #4
Виктор_Сен, как вариант - перегрузить операторы для нужных вам типов, и в них выполнять проверки.
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;
}
в ВС еще проще, он позволяет ассемблерным вставкам обращаться к меткам за пределами ассемблерной вставки, в гсс вроде такой трюк не прокатывает
Петррр
10.11.2011, 14:39
  #6

Не по теме:

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

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

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

Не по теме:

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

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

talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
10.11.2011, 14:48     СИ++ и контроль переполнения #8
-=ЮрА=-, а если нужно контролировать переполнение в unsigned long long или long long double?
Net_Wanderer
235 / 208 / 19
Регистрация: 08.06.2011
Сообщений: 467
10.11.2011, 14:49     СИ++ и контроль переполнения #9
Цитата Сообщение от talis Посмотреть сообщение
Виктор_Сен, как вариант - перегрузить операторы для нужных вам типов, и в них выполнять проверки.
Насколько я помню, нельзя перегружать операторы для базовых типов данных.
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 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;
}
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
10.11.2011, 21:42     СИ++ и контроль переполнения #11
talis, разумеется, ведь шаблонная обёртка не подпадает под понятие "базовый тип"
-=ЮрА=-
Заблокирован
Автор 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;
}
Миниатюры
СИ++ и контроль переполнения  
-=ЮрА=-
Заблокирован
Автор FAQ
11.11.2011, 10:49     СИ++ и контроль переполнения #13
PS:
Цитата Сообщение от talis Посмотреть сообщение
-=ЮрА=-, а если нужно контролировать переполнение в unsigned long long или long long double?
- руководствуясь приведенной мной логикой можно контролировать и эти типы...
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
11.11.2011, 12:18     СИ++ и контроль переполнения #14
-=ЮрА=-, без введения обёрток математическая формула, реализованная вашим способом, станет абсолютно нечитаемой.
-=ЮрА=-
Заблокирован
Автор 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;
}
- я пока не пишу что он не реализует предполагаемую задачу, т.к. возможно вы именно как обворачивать без обработки исключений представить хотели...

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

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

Не по теме:

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

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 оператор используется, и как бы нельзя проверить переполнение, а то я уже было обрадовался
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
11.11.2011, 14:41     СИ++ и контроль переполнения #19
LosAngeles, да, спасибо. Должно быть так:

C++
1
a = int_v(12) + 8;
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.11.2011, 15:01     СИ++ и контроль переполнения
Еще ссылки по теме:

C++ Отлов исключения переполнения буфера
C++ Флаг переполнения
C++ Как отловить переполнения?

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

Или воспользуйтесь поиском по форуму:
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16825 / 5246 / 321
Регистрация: 30.03.2009
Сообщений: 14,126
Записей в блоге: 26
11.11.2011, 15:01     СИ++ и контроль переполнения #20
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от Виктор_Сен Посмотреть сообщение
Можно ли как-нибудь в VS включить контроль переполнения при математических вычислениях? Чтоб, например, возникало исключение. Или это можно сделать только средствами ассемблера путём контроля флагов?
О каких переполнениях идёт речь?

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

Если же речь идёт о плавающих вычислениях, то оно как правило процессорами поддерживается, потому что прерывания требуются по стандарту ieee-754. Для этого есть стандартные функции типа http://linux.die.net/man/3/feenableexcept но они, насколько я знаю, входят в стандарт Си99
Yandex
Объявления
11.11.2011, 15:01     СИ++ и контроль переполнения
Ответ Создать тему
Опции темы

Текущее время: 00:05. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru