Информация об изменениях

Сообщение Re[8]: Carbon от 19.04.2024 11:15

Изменено 19.04.2024 11:29 vdimas

Re[8]: Carbon
Здравствуйте, Sinclair, Вы писали:

V>>В данном случае ты даёшь оценку своим фантазиям, бо архитектуры/компиляторы явно определяют своё поведение при переполнении.

S>Ошибаетесь. Я же привёл пример. Каким образом "явно определённое поведение" приводит к разнице между -O0 и -O2 для приведённого фрагмента?

1. Твой пример содержит ошибки, например, для short, т.к. значением short(value)+1 будет значение типа int, т.е. еще до рассуждений об UB необходимо исправить ошибку:
template<typename signed_integral>
bool is_max(signed_integral value) {
    return signed_integral(value + 1) < value;
}



S>Что мы и наблюдаем в приведённом примере.


2. Мы наблюдаем невладение предметом, бо в C/C++ еще есть битовые поля, для которых это однозначное UB со всеми спецификациями платформы:
int main()
{
    struct S {
        int field1 : 8,
            field2 : 7,
            flag : 1;
    } s = { 127, 63, 1 };

    std::cout
        << (is_max(s.field1) ? "wow " : "oops ")
        << (is_max(s.field2) ? "wow " : "oops ")
        << (is_max(s.flag) ? "wow " : "oops ")
        << std::endl;

    using sbyte = signed char;
    
    std::cout
        << (is_max(static_cast<sbyte>(127)) ? "wow " : "oops ")
        << (is_max(static_cast<short>(32767)) ? "wow " : "oops ")
        << std::endl;

    return 0;
}



V>>Т.е. можно подобрать такое кодирование, что в твоём коде будет UB именно для этой платформы, например, для обратного кодирования есть два нуля для знаковых чисел — 0000 и 1111, где при сравнении первый ноль меньше второго, и твоя программа закономерно поломалась, как и предостерегал стандарт.

S> Нет. Не угадали.

фуф, тяжело с тобой...
Такое ощущение, что тебе всю жизнь пришлось работать среди откровенно тупых людей. ))
Мои соболезнования, кстате.
Но что в любом обсуждении ты теперь на рефлексах считаешь собеседников по-умолчанию идиотами, и даже не мелькает мысли проверить себя — это изрядно утомляет, конечно...


S>Программа прекрасно ломается на совершенно любой платформе.


Программа ломается, потому что в ней ошибки. ))
Ты написал некий обощённый код из некоторого обощённого предположения, но это предположение для многих ситуаций ложно.

Фишка в том, что для промежуточных вычислений в железе часто используют регистры шириной в слово, т.е. UB возникает прямо в железе — ты можешь проверить это на последних gcc на x64, там будет тот же эффект в рантайм для int, что и в случае short(value)+1, т.е. даже в рантайме программа сломается (без оптимизации), потому что в ней ошибка — ты не можешь гарантировать ширину бит промежуточных вычислений.
Re[8]: Carbon
Здравствуйте, Sinclair, Вы писали:

V>>В данном случае ты даёшь оценку своим фантазиям, бо архитектуры/компиляторы явно определяют своё поведение при переполнении.

S>Ошибаетесь. Я же привёл пример. Каким образом "явно определённое поведение" приводит к разнице между -O0 и -O2 для приведённого фрагмента?

1. Твой пример содержит ошибки, например, для short, т.к. значением short(value)+1 будет значение типа int, т.е. еще до рассуждений об UB необходимо исправить ошибку:
template<typename signed_integral>
bool is_max(signed_integral value) {
    return signed_integral(value + 1) < value;
}



S>Что мы и наблюдаем в приведённом примере.


2. Мы наблюдаем невладение предметом, бо в C/C++ еще есть битовые поля, для которых это однозначное UB со всеми спецификациями платформы:
int main()
{
    struct S {
        int field1 : 8,
            field2 : 7,
            flag : 1;
    } s = { 127, 63, 1 };

    std::cout
        << (is_max(s.field1) ? "wow " : "oops ")
        << (is_max(s.field2) ? "wow " : "oops ")
        << (is_max(s.flag) ? "wow " : "oops ")
        << std::endl;

    using sbyte = signed char;
    
    std::cout
        << (is_max(static_cast<sbyte>(127)) ? "wow " : "oops ")
        << (is_max(static_cast<short>(32767)) ? "wow " : "oops ")
        << std::endl;

    return 0;
}



V>>Т.е. можно подобрать такое кодирование, что в твоём коде будет UB именно для этой платформы, например, для обратного кодирования есть два нуля для знаковых чисел — 0000 и 1111, где при сравнении первый ноль меньше второго, и твоя программа закономерно поломалась, как и предостерегал стандарт.

S> Нет. Не угадали.

фуф, тяжело с тобой...
Такое ощущение, что тебе всю жизнь пришлось работать среди откровенно тупых людей. ))
Мои соболезнования, кстате.
Но что в любом обсуждении ты теперь на рефлексах считаешь собеседников по-умолчанию идиотами, и даже не мелькает мысли проверить себя — это изрядно утомляет, конечно...


S>Программа прекрасно ломается на совершенно любой платформе.


Программа ломается, потому что в ней ошибки. ))
Ты написал некий обощённый код из некоторого обощённого предположения, но это предположение для многих ситуаций ложно.

Фишка в том, что для промежуточных вычислений в железе часто используют регистры шириной в слово, т.е. UB возникает прямо в железе — ты можешь проверить это на последних gcc на x64, там будет тот же эффект в рантайм для int, что и в случае short(value)+1, т.е. даже в рантайме программа сломается (без оптимизации), потому что в ней ошибка — ты не можешь гарантировать ширину бит промежуточных вычислений, т.е. не можешь гарантировать, что переполнение действительно произойдет.