1. C++ / Говнокод #26205

    +3

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    #include <iostream>
     
    using namespace std;
     
    class lock_guard_ext{
    public:
        lock_guard_ext() { cout << "lock_guard_ext ctor" << endl; }
        ~lock_guard_ext() { cout << "lock_guard_ext dtor" << endl; }
    };
     
    struct Access {
        lock_guard_ext lock;
        int & ref_to_value;
    };
     
    int & t() {
        throw 0;
    }
    
    Access foo1() {
        return { {}, t() };
    }
     
    int main () {
        try {
            volatile auto a = foo1();
        } catch (int) {
     
        }
    }

    В шланге деструктор вызывается, в gcc не вызывается.
    https://wandbox.org/permlink/7sbsqzhbo0o7dOse

    Запостил: j123123, 12 Декабря 2019

    Комментарии (33) RSS

    • Говно это ваше RAII
      Ответить
    • Какой багор )))

      Впрочем, причём здесь RAII я так и не понял. Баг-то не в RAII, баг в «GCC».
      Ответить
      • Баг в GCC связанный с RAII.
        Вот если взять сишку, вручную свои деструкторы и конструкторы пилить без всей этой дрисни с trow catch и прочей хуйни, такого бы не было.

        Если серьезно, язык C++ настолько запутан и погряз во всякой хуйне, что вряд ли сегодня существует хотя бы один незабагованный C++ компилятор, полностью соответствующий стандарту (пусть даже и не самому свежему, C++98, С++03 или C++11 там)
        Ответить
        • Например вот
          https://bugs.llvm.org/show_bug.cgi?id=7469
          https://gcc.gnu.org/bugzilla/show_bug.cgi?id=29027

          тот же самый баг в Clang и GCC
          Притом в GCC он висит аж с 2006 года
          Ответить
        • КАКОЙ БАГОР
          Ответить
        • Ну да, кресты — адово перегруженное говно, сложность создания компилятора для которого сравнима со сложностью постройки космического корабля. Именно поэтому…
          Ответить
          • Я вспомнил Дейкстру: http://govnokod.ru/25987#comment513029

            Если для него 600 страниц стандарта — это слишком сложно, чтобы построить компилятор с прогнозируемым поведением, то что же для него крестостандарт?
            Ответить
            • Не тот язык назвали "языком ада"...
              Ответить
              • Примечательно, что гения-злодея из "Дикий вест" звали доктор Лавлесс.
                Доводится ли он Адочке?
                Ответить
            • Поэтому я за brainfuck - там стандарт поместится на полстраницы.
              Ответить
        • Французы написали компилятор сишки на языке со смешным названием «Петух»:
          https://en.wikipedia.org/wiki/CompCert
          https://ru.wikipedia.org/wiki/CompCert

          Они обещают, что компилятор будет гарантированно выдавать код, соответствующий исходнику. Правда, им пришлось что-то удалить из языка (кажется, поддержку устройства Даффа).

          За компилятор же крестов с математической гарантией даже в «INRIA» не взялись.
          Ответить
          • http://compcert.inria.fr/compcert-C.html

            CompCert C supports all of ISO C 99, with the following exceptions:

            • switch statements must be structured as in MISRA-C; unstructured "switch", as in Duff's device, is not supported.
            • longjmp and setjmp are not guaranteed to work.
            • Variable-length array types are not supported.

            Consequently, CompCert supports all of the MISRA-C 2004 subset of C, plus many features excluded by MISRA (such as recursive functions and dynamic heap memory allocation).

            Ну вот, ещё setjmp/longjmp не гарантируют и VLA не осилили.
            Ответить
          • > Они обещают, что компилятор будет гарантированно выдавать код, соответствующий исходнику.

            Можно вместо этого проверять бинарник, который выдал компилятор. Т.е. доказывать, что он по смыслу соответствует исходнику:

            https://en.wikipedia.org/wiki/L4_microkernel_family#High_assurance:_se L4

            > The NICTA team also proved correctness of the translation from C to executable machine code, taking the compiler out of the trusted computing base of seL4. This implies that the high-level security proofs hold for the kernel executable
            Ответить
        • А Ви таки-уверены, что конпелятор не заинлайнил самым анальным образом результат t() в нечто, что уже не int, или не сыграл под std::terminate, посчитав, что и так знает, что произойдет? Потому что может быть вот так:

          C++11 15.5.1 The std::terminate() function [except.terminate]
          2 … In the situation where no matching handler is found, it is implementation-defined whether or not the stack is unwound before std::terminate() is called.
          Ответить
          • Это уже никого не волнующие детали реализации. Конпелятор создал временный объект, вызвал его коньструктор — а десруктор не вызвал. Это крайне серьёзный баг, нарушающий Стандарт и способный привести к утечкам ресурсов.
            Ответить
            • Так
              >implementation-defined whether or not the stack is unwound
              Стеки не крутятся, деструкторы не мутятся же, явно сказано, что пусть там std::terminate (предполагаемый) ебётся.
              Ответить
              • Здесь вполне себе есть «matching handler», и никакого std::terminate вообще нет:
                #include <iostream>
                using namespace std;
                class lock_guard_ext{
                public:
                    lock_guard_ext() { cout << "lock_guard_ext ctor" << endl; }
                    ~lock_guard_ext() { cout << "lock_guard_ext dtor" << endl; }
                };
                
                struct Access {
                    lock_guard_ext lock;
                    int x;
                };
                
                int t() {
                    throw 0;
                }
                
                Access foo1() {
                    return { {}, t() };
                }
                int main () {
                    try {
                        volatile auto a = foo1();
                    } catch (int) {
                        cout << "int catched!" << endl;
                    }
                    cout << "Bye-bye." << endl;
                }

                https://wandbox.org/permlink/KMo3T8EeLfSAwkYE
                Это баг в «GCC».
                Ответить
      • КАКОЙ БАГОР )))
        Ответить
    • КАКОЙ БАГОР
      Ответить
    • КАКОЙ БАГОР
      Ответить
    • КАКОЙ БАГОР
      Ответить
    • КАКОЙ БАГОР
      Ответить
    • КАКОЙ БАГОР
      Ответить

    Добавить комментарий