Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.70/50: Рейтинг темы: голосов - 50, средняя оценка - 4.70
36 / 29 / 2
Регистрация: 01.08.2011
Сообщений: 176
1

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

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

Author24 — интернет-сервис помощи студентам
Можно ли как-нибудь в VS включить контроль переполнения при математических вычислениях? Чтоб, например, возникало исключение. Или это можно сделать только средствами ассемблера путём контроля флагов?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
10.11.2011, 13:03
Ответы с готовыми решениями:

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

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

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

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

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
3528 / 2686 / 334
Регистрация: 11.03.2009
Сообщений: 6,168
10.11.2011, 14:32 3
-=ЮрА=-, как это может помочь при контроле выполнения математических операций?
0
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
10.11.2011, 14:34 4
Виктор_Сен, как вариант - перегрузить операторы для нужных вам типов, и в них выполнять проверки.
1
Заблокирован
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
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
10.11.2011, 14:48 8
-=ЮрА=-, а если нужно контролировать переполнение в unsigned long long или long long double?
0
237 / 210 / 29
Регистрация: 08.06.2011
Сообщений: 467
10.11.2011, 14:49 9
Цитата Сообщение от talis Посмотреть сообщение
Виктор_Сен, как вариант - перегрузить операторы для нужных вам типов, и в них выполнять проверки.
Насколько я помню, нельзя перегружать операторы для базовых типов данных.
2
794 / 546 / 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
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
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
794 / 546 / 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
794 / 546 / 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
Заблокирован
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
794 / 546 / 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
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
11.11.2011, 15:01 20
Лучший ответ Сообщение было отмечено как решение

Решение

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

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

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru