оптимизация gcc? ошибка? и его practial импликация к проекту

Мои вопросы разделены на три части

Вопрос 1
Рассмотрите ниже кода,

#include <iostream>
using namespace std;

int main( int argc, char *argv[])
{

    const int v = 50;
    int i = 0X7FFFFFFF;

    cout<<(i + v)<<endl;

    if ( i + v < i )
    {
        cout<<"Number is negative"<<endl;
    }
    else
    {
        cout<<"Number is positive"<<endl;
    }

    return 0;
}

Никакие определенные опции оптимизации компилятора не используются, или флаг O используется. Это - основная команда g компиляции ++-o, тестируют main.cpp, используется для формирования исполняемого файла.

По-видимому очень простой код, имеет нечетное поведение в SUSE 64 бита ОС, gcc версия 4.1.2. Ожидаемый вывод является "Числом, отрицательно", вместо этого только в SUSE 64 бита ОС, вывод был бы "Числом, положительно".

После некоторого объема анализа и выполнения 'disass' кода, я нахожу, что компилятор оптимизирует в ниже формата -

  • Так как я - то же с обеих сторон сравнения, оно не может быть изменено в том же выражении, удалить 'меня' из уравнения.
  • Теперь, сравнение приводит к if ( v < 0 ), где v является положительной константой, Таким образом, во время самой компиляции, еще адрес функции суда части добавляется к регистру. Никакие cmp/jmp инструкции не могут быть найдены.

Я вижу, что поведение находится только в gcc 4.1.2 SUSE 10. При попытке в AIX 5.1/5.3 и HP IA64 результат как ожидалось.

Допустима вышеупомянутая оптимизация?
Или, действительно ли использование является водосливным механизмом для интервала не допустимый вариант использования?

Вопрос 2
Теперь, когда я изменяю условный оператор от if (i + v < i) кому: if ( (i + v) < i ) даже затем поведение - то же, это по крайней мере я лично не согласился бы, так как дополнительные фигурные скобки обеспечиваются, я ожидаю, что компилятор для создания временной встроенной переменной типа и их выдерживает сравнение, таким образом аннулирует оптимизацию.

Вопрос 3
Предположим, что у меня есть огромная кодовая база, я перемещают мою версию компилятора, такая ошибка/оптимизация может вызвать опустошение в моем поведении системы. Конечно, с бизнес-точки зрения, это очень неэффективно для тестирования всех строк кода снова только из-за компилятора upgradation.

Я думаю для всей практической цели, эти виды ошибки очень трудно поймать (во время upgradation) и неизменно будут пропущены к месту производства.

Кто-либо может предложить какой-либо возможный способ удостовериться, чтобы гарантировать, что подобные ошибка/оптимизация не оказывает влияния на мою существующую систему/кодовую базу?


PS:

  • Когда константа для v удалена из кода, затем оптимизация не сделана компилятором.
  • Я верю, это прекрасно подходит для использования водосливного механизма, чтобы найти, ли переменная от МАКСА - 50 значений (в моем случае).

Обновление (1)
Чего я хотел бы достигнуть? переменная я был бы счетчиком (вид syncID). Если бы я делаю офлайновую операцию (50 операций) затем во время запуска, я хотел бы сбросить свой счетчик, Для этого я проверяю граничное значение (для сброса его) вместо того, чтобы добавить его вслепую.

Я не уверен, полагаюсь ли я на аппаратную реализацию. Я знаю, что 0X7FFFFFFF является макс. положительным значением. Все, что я делаю, путем увеличивания стоимость этого, я ожидаю, что возвращаемое значение будет отрицательно. Я не думаю, что эта логика имеет какое-либо отношение к аппаратной реализации.

Так или иначе, все спасибо за Ваш вход.


Обновление (2)
Большинство inpit указывает, что я полагаюсь на более низкое поведение уровня на проверке переполнения. У меня есть вопросы относительно того же,

  • Если это так, Для неподписанного интервала, как я проверяю и сбрасываю значение во время потери значимости или переполнения? как то, если v=10, i=0X7FFFFFFE, я хочу сброс i = 9. Так же для потери значимости?

Я не смог бы сделать это, если я не проверяю на отрицательность числа. Таким образом, мое требование состоит в том, что интервал должен возвратить отрицательное число, когда значение добавляется к +MAX_INT.

Сообщите мне свои исходные данные.

11
задан BalusC 23 October 2011 в 14:21
поделиться

4 ответа

Это известная проблема, и я не думаю, что она считается ошибкой в ​​компиляторе. Когда я компилирую с gcc 4.5 с -Wall -O2 , он предупреждает

предупреждение: при условии, что подписанное переполнение не происходит, если предполагается, что (X + c)

Хотя ваш код вызывает переполнение .

Вы можете передать флаг -fno-strict-overflow , чтобы отключить данную оптимизацию.

11
ответ дан 3 December 2019 в 07:36
поделиться

Q1: Возможно, число действительно положительное в 64-битной реализации? Кто знает? Перед отладкой кода я бы просто printf ("% d", i + v);

Q2: круглые скобки нужны только для того, чтобы сообщить компилятору, как анализировать выражение. Обычно это делается в виде дерева, поэтому оптимизатор вообще не видит скобок. И выражение можно изменить бесплатно.

Q3: Вот почему, как программист c / c ++, вы не должны писать код, предполагающий определенные свойства базового оборудования, такие как, например, что int - это 32-битная величина в форме дополнения до двух.

2
ответ дан 3 December 2019 в 07:36
поделиться

Что выводит строка:

cout<<(i + v)<<endl;

в примере SUSE? Вы уверены, что у вас нет 64-битных целых чисел?

0
ответ дан 3 December 2019 в 07:36
поделиться

Ваш код приводит к неопределенному поведению. Языки C и C++ не имеют "механизма переполнения" для целочисленной арифметики со знаком. Ваши вычисления переполняют знаковые целые числа - поведение сразу же становится неопределенным. Рассмотрение этого с позиции "ошибка в компиляторе или нет" ничем не отличается от попытки анализа примеров i = i++ ++i.

Компилятор GCC имеет оптимизацию, основанную на этой части спецификации языков Си/Си++. Она называется "строгая семантика переполнения" или что-то вроде этого. Она основана на том, что добавление положительного значения к знаковому целому числу в C++ всегда дает большее значение или приводит к неопределенному поведению. Это сразу же означает, что компилятор совершенно свободно может считать, что сумма всегда больше. Общая природа этой оптимизации очень похожа на оптимизацию "strict aliasing", которая также присутствует в GCC. Обе они привели к некоторым жалобам со стороны более "хакерски настроенной" части сообщества пользователей GCC, многие из которых даже не подозревали, что трюки, на которые они полагались в своих программах на C/C++, были просто незаконными хаками.

3
ответ дан 3 December 2019 в 07:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: