С++ exception-safety, промышленное программирование и кадры.
От: _Winnie Россия C++.freerun
Дата: 29.11.05 23:28
Оценка:
вот здесь у нас вышел небольшой спор по поводу исключений.
В связи с этим, есть примеры большого-среднего софта, написанного командой от 5 человек на С++ в "правильном exception-safe" стиле c грамотным применением исключений?

Или exception-safety и коммандный труд несовместимы, либо требуют слишком квалифицированных С++ программистов?

Долго думал над группой, решил всё-таки в С++.
Правильно работающая программа — просто частный случай Undefined Behavior
Re: С++ exception-safety, промышленное программирование и ка
От: _Winnie Россия C++.freerun
Дата: 29.11.05 23:34
Оценка: :))) :)
4. Меморилик — злое мифическое существо по мнению дотнетчиков проживающее в каждой программе на C++. ( (с) WolfHound )
Правильно работающая программа — просто частный случай Undefined Behavior
Re: С++ exception-safety, промышленное программирование и ка
От: Павел Кузнецов  
Дата: 30.11.05 01:19
Оценка:
_Winnie,

> вот здесь у нас вышел небольшой спор по поводу исключений.

> В связи с этим, есть примеры большого-среднего софта, написанного командой от 5 человек на С++ в "правильном exception-safe" стиле c грамотным применением исключений?

Смотря что понимать под "правильным exception-safe стилем". Если речь идет об осознанном выборе тех или иных гарантий exception safety и последующей заботе об их выполнении, то да, примеры встречаются.

> Или exception-safety и коммандный труд несовместимы, либо требуют слишком квалифицированных С++ программистов?


К сожалению, корректная обработка "ошибочных" ситуаций в любом случае требует определенной квалификации, а без использования исключений -- еще и изрядно больших усилий.
Posted via RSDN NNTP Server 2.0
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[2]: С++ exception-safety, промышленное программирование и
От: _Winnie Россия C++.freerun
Дата: 30.11.05 01:52
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>_Winnie,

ПК>Смотря что понимать под "правильным exception-safe стилем". Если речь идет об осознанном выборе тех или иных гарантий exception safety и последующей заботе об их выполнении, то да, примеры встречаются.


Понимаю использование исключений вместо кодов возврата/GetLastError() и кучи if-ов, и так, что бы при этом не было мемориликов/падений программы из-за дважды вызванного деструктора/и тп.

>> Или exception-safety и коммандный труд несовместимы, либо требуют слишком квалифицированных С++ программистов?


ПК>К сожалению, корректная обработка "ошибочных" ситуаций в любом случае требует определенной квалификации, а без использования исключений -- еще и изрядно больших усилий.


Ну, я в том смысле что программист сам делает условные переходы, и видит где у него что не освобождается.
А видеть неявные переходы нужно привыкнуть. Техника "все освобождаем в деструкторах" помогает, но только в 98% случаев. У Саттера есть примеры очень хитрых утечек памяти. Например 90% "bycicle_hand_made_shared_ptr" не exception-safe, так как забывают освободить объект, если выделение памяти под счётчик кинуло исключение.
Правильно работающая программа — просто частный случай Undefined Behavior
Re[3]: С++ exception-safety, промышленное программирование и
От: _Winnie Россия C++.freerun
Дата: 30.11.05 01:55
Оценка:
Здравствуйте, _Winnie, Вы писали:
_W>Здравствуйте, Павел Кузнецов, Вы писали:
ПК>>_Winnie,


_W>Ну, я в том смысле что программист сам делает условные переходы, и видит где у него что не освобождается.

_W>А видеть неявные переходы нужно привыкнуть. Техника "все освобождаем в деструкторах" помогает, но только в 98% случаев. У Саттера есть примеры очень хитрых утечек памяти. Например 90% "bycicle_hand_made_shared_ptr" не exception-safe, так как забывают освободить объект, если выделение памяти под счётчик кинуло исключение.

И, например, если я не прочитал бы об этом у Мейерса/Саттера, то я вряд ли бы об этом сам догадался. (например, о f(auto_ptr(new A), auto_ptr(new B))).
А сколько ещё таких закидонов, которые увидит глаз Саттера, а мой не увидит?
Правильно работающая программа — просто частный случай Undefined Behavior
Re[4]: С++ exception-safety, промышленное программирование и
От: Павел Кузнецов  
Дата: 30.11.05 02:11
Оценка:
_Winnie,

> А сколько ещё таких закидонов, которые увидит глаз Саттера, а мой не увидит?


А результат, который возвращает, скажем, [s][n]printf, ты/твои коллеги всегда проверяешь/ют?
Posted via RSDN NNTP Server 2.0
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[5]: С++ exception-safety, промышленное программирование и
От: _Winnie Россия C++.freerun
Дата: 30.11.05 03:10
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>_Winnie,
>> А сколько ещё таких закидонов, которые увидит глаз Саттера, а мой не увидит?

ПК>А результат, который возвращает, скажем, [s][n]printf, ты/твои коллеги всегда проверяешь/ют?

Да, но memory-ликов от этого вроде не возникает.
s[n]printf не очень хороший пример, так как при неправильном format string программа просто UBится.
А IO ошибки printf безопасны. И зачастую правильной реакцией на них является игнорирование.

И сломавшийся printf — вещь теоретическая.
А вот от того, что из-за исключения в в одном файле у меня(у моего коллеги) не закроется другой файл и будут утечки памяти — это вещь практическая.
Правильно работающая программа — просто частный случай Undefined Behavior
Re[6]: С++ exception-safety, промышленное программирование и
От: _Winnie Россия C++.freerun
Дата: 30.11.05 03:12
Оценка:
Здравствуйте, _Winnie, Вы писали:

ПК>>А результат, который возвращает, скажем, [s][n]printf, ты/твои коллеги всегда проверяешь/ют?

_W>Да, но memory-ликов от этого вроде не возникает.
"Да" в том смысле, что я согласен с тем, что не проверяют
Правильно работающая программа — просто частный случай Undefined Behavior
Re[6]: С++ exception-safety, промышленное программирование и
От: _Winnie Россия C++.freerun
Дата: 30.11.05 03:14
Оценка:
Здравствуйте, _Winnie, Вы писали:

ПК>>А результат, который возвращает, скажем, [s][n]printf, ты/твои коллеги всегда проверяешь/ют?

И если идёт о чём-то очень серьёзном, скажем о ядре OS, то там проверяется всё.
Правильно работающая программа — просто частный случай Undefined Behavior
Re[6]: С++ exception-safety, промышленное программирование и
От: _Winnie Россия C++.freerun
Дата: 30.11.05 03:31
Оценка:
Да, кстати, специфика у меня такая — невыгруженные из видеопамяти текстуры для меня фатальны, а вот то, что atoi не проверяет переполнения и никак не диагностирует ошибку — хрен с ним.
Правильно работающая программа — просто частный случай Undefined Behavior
Re[6]: С++ exception-safety, промышленное программирование и
От: Павел Кузнецов  
Дата: 30.11.05 03:41
Оценка:
_Winnie,

> ПК> А результат, который возвращает, скажем, [s][n]printf, ты/твои коллеги всегда проверяешь/ют?


> Да, но memory-ликов от этого вроде не возникает.


Memory leaks -- единственная или самая существенная неприятность, которая может произойти при обработке ошибочных ситуаций (вне зависимости от выбранного механизма)? В какой степени использование исключений изменяет вероятность получения memory leak? Какие техники ты применяешь без использования исключений для избежания memory leaks, и почему эти техники не помогают тебе в случае использования исключений?
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[7]: С++ exception-safety, промышленное программирование и
От: Павел Кузнецов  
Дата: 30.11.05 03:49
Оценка: +1
_Winnie,

> ПК>>А результат, который возвращает, скажем, [s][n]printf, ты/твои коллеги всегда проверяешь/ют?


> _W> Да, но memory-ликов от этого вроде не возникает.


> "Да" в том смысле, что я согласен с тем, что не проверяют


И это верно далеко не только для [s][n]printf, приведенного в качестве примера. Это я к тому, что отсутствие проблем, вызванных прерыванием потока исполнения исключениями приводит к другим проблемам. Ни те, ни другие не решаются сами собой, а нуждаются в строгой дисциплине со стороны программиста. В случае использования исключений у программиста появляется инструмент, позволяющий избавиться от значительного объема рутинных проверок, необходимых в случае работы с кодами возврата. Каждый выбирает для себя.
Posted via RSDN NNTP Server 2.0
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[7]: С++ exception-safety, промышленное программирование и
От: Павел Кузнецов  
Дата: 30.11.05 04:05
Оценка:
_Winnie,

> Да, кстати, специфика у меня такая — невыгруженные из видеопамяти текстуры для меня фатальны, а вот то, что atoi не проверяет переполнения и никак не диагностирует ошибку — хрен с ним.


В той же степени могут оказаться фатальными и попытки работать с каким-нибудь контекстом, если при его создании произошла проигнорированная ошибка.
Posted via RSDN NNTP Server 2.0
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[7]: С++ exception-safety, промышленное программирование и
От: Павел Кузнецов  
Дата: 30.11.05 04:16
Оценка: 3 (1)
_Winnie,

> ПК>>А результат, который возвращает, скажем, [s][n]printf, ты/твои коллеги всегда проверяешь/ют?


> И если идёт о чём-то очень серьёзном, скажем о ядре OS, то там проверяется всё.


Кстати, в "Философии" как раз сейчас подходящий топик идет. Вот приблизительное место кульминации на данный момент: http://rsdn.ru/forum/?mid=1512953
Автор: IT
Дата: 30.11.05
Posted via RSDN NNTP Server 2.0
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[4]: С++ exception-safety, промышленное программирование и
От: Павел Кузнецов  
Дата: 30.11.05 06:25
Оценка: 61 (8) +3 :))
_Winnie,

> f(auto_ptr(new A), auto_ptr(new B))


(Заранее прошу прощения за диалог с собой.)

  • Будет ли в общем случае корректно работать данный код, если new будет возвращать 0 при нехватке памяти? (Не будет, т.к. в общем случае нет гарантий, что f ожидает нулевые указатели.)

  • Как его переписать, чтобы он работал корректно? (Вынести создание объектов в отдельные statements, снабдив соответствующими проверками.)

    ErrCode g()
    {
       std::auto_ptr<A> a(new (std::nothrow) A);
       if (!a)
         return out_of_memory_error;
    
       std::auto_ptr<B> b(new (std::nothrow) B);
       if (!b)
         return out_of_memory_error;
    
       return f(a, b);
    }


  • Будет ли переписанный код корректно работать в присутствии исключений? (Да. Более того, его можно даже сократить.)

    void g()
    {
       std::auto_ptr<A> a(new A);
       std::auto_ptr<B> b(new B);
       f(a, b);
    }


  • Какой недостаток получившегося корректного кода "с исключениями"? (Неграмотный программист может попытаться "упростить" его, приведя в первоначальный вид.)

  • Что с этим делать? (Имхо, нанимать грамотных программистов, т.к. неграмотные с тем же успехом "упростят" его и в случае отказа от исключений, и мы вернемся к началу данного сообщения.)
    Posted via RSDN NNTP Server 2.0
  • Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
    Re[8]: С++ exception-safety, промышленное программирование и
    От: Коваленко Дмитрий Россия http://www.ibprovider.com
    Дата: 30.11.05 09:46
    Оценка: +1
    Здравствуйте, Павел Кузнецов, Вы писали:

    ПК>_Winnie,


    >> Да, кстати, специфика у меня такая — невыгруженные из видеопамяти текстуры для меня фатальны, а вот то, что atoi не проверяет переполнения и никак не диагностирует ошибку — хрен с ним.


    ПК>В той же степени могут оказаться фатальными и попытки работать с каким-нибудь контекстом, если при его создании произошла проигнорированная ошибка.


    Вот, кстати, ловушка для VBScript-программеров. Конструкторы классов (в виде sub class_initialize()) не кидают исключения. Хотя глобальный объект err "взводится". В результате получаем недоделанный объект, который начинает брыкаться.
    -- Пользователи не приняли программу. Всех пришлось уничтожить. --
    Re[5]: С++ exception-safety, промышленное программирование и
    От: MaximE Великобритания  
    Дата: 30.11.05 10:43
    Оценка:
    On Wed, 30 Nov 2005 02:11:19 -0000, Павел Кузнецов <5834@users.rsdn.ru> wrote:

    > _Winnie,

    >
    >> А сколько ещё таких закидонов, которые увидит глаз Саттера, а мой не увидит?
    >
    > А результат, который возвращает, скажем, [s][n]printf, ты/твои коллеги всегда проверяешь/ют?

    Тут можно сенца подстелить:

    #if defined(__GNUC__) && ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ > 3)
    #   define EX_PRINTF_LIKE(a, b) __attribute__((format(printf,a,b)))
    #else
    #   define EX_PRINTF_LIKE(a, b)
    #endif
    
    inline size_t snprintf_ex(char* buf, size_t buf_size, const char *fmt, ...)
         EX_PRINTF_LIKE(3,4);
    
    inline size_t snprintf_ex(char* buf, size_t buf_size, const char *fmt, ...)
    {
         va_list ap; va_start(ap, fmt);
         size_t n = ::vsnprintf(buf, buf_size, fmt, ap);
         va_end(ap);
         if(buf_size <= n)
             throw std::logic_error("vsnprintf");
         return n;
    }


    --
    Maxim Yegorushkin
    Posted via RSDN NNTP Server 2.0
    Re[6]: С++ exception-safety, промышленное программирование и
    От: srggal Украина  
    Дата: 30.11.05 10:58
    Оценка: +2
    Здравствуйте, MaximE, Вы писали:

    []

    И куда заведет нас это сено в контексте данной дискуссии о использовании исключений

    ... << RSDN@Home 1.1.4 stable rev. 510>>
    Re[5]: С++ exception-safety, промышленное программирование и
    От: eao197 Беларусь http://eao197.blogspot.com
    Дата: 01.12.05 11:01
    Оценка:
    Здравствуйте, Павел Кузнецов, Вы писали:

    ПК>_Winnie,


    >> f(auto_ptr(new A), auto_ptr(new B))


    ПК>(Заранее прошу прощения за диалог с собой.)


    ПК>
  • Будет ли в общем случае корректно работать данный код, если new будет возвращать 0 при нехватке памяти? (Не будет, т.к. в общем случае нет гарантий, что f ожидает нулевые указатели.)

    [...skipped...]

    Если бы дело только этим ограничивалось Этот пример, имхо, из разряда проблем, которые могут произойти крайне редко.
    Я вот вчера переделывал код, который работал приблизительно так:
    void handle_trx( const some_trx_t & trx )
        {
            try
                {
                    // Здесь проверяем возможность проведения транзакции.
                    // Если это не возможно, то исключения валятся именно здесь.
                    check_trx( trx );
                    
                    // Транзакция запускается на выполнение.
                    initiate_trx( trx );
                }
            catch( const trx_handle_ex_t & x )
                {
                    send_negative_response( trx );
                }
            catch( const std::exception & x )
                {
                    // Все, произошло что-то непредвиденное.
                    log_unexpected_error( x );
                    // Ничего не предпринимаем, т.к. падать дальше не куда,
                    // а все ресурсы в этой точке должны быть освобождены.
                }
        }
        
    void initiate_trx( const some_trx_t & trx )
        {
            // Сохраняем описание транзакции на будущее.
            store_trx_info( trx );
            
            // Передаем транзакцию конкретному исполнителю.
            send_trx( trx );
        }


    В общем, спустя много времени после написания этого кода, я вижу в не несколько огрехов. Но заострить внимание хочу на функции initiate_trx(). Как оказалось, в нескольких случаях (при особых значениях некоторых полей в trx) исключения кидала функция send_trx(). Но уже после того, как информация о транзакции была сохранена! Т.е. транзакция никуда не ушла, но мы про нее помним. И по истечении тайм-аута можем возвращать не правильный результат (не правильный потому, что реально обработки транзакции не было). Следовало бы переписать initiate_trx() как-то так:
    void initiate_trx( const some_trx_t & trx )
        {
            // Сохраняет описание транзакции в конструкторе.
            store_trx_info_guard_t guard( trx );
            
            send_trx( trx );
            guard.commit(); // Если этого не сделать, то guard в деструкторе
                            // удалит описание транзакции.
        }


    Да только вот изначально это сделано не было (даже не помню уже почему), а со временем вылезло.
    ... << RSDN@Home 1.1.4 stable rev. 510>>


  • SObjectizer: <микро>Агентно-ориентированное программирование на C++.
    Re: С++ exception-safety, промышленное программирование и ка
    От: Tom Россия http://www.RSDN.ru
    Дата: 01.12.05 13:12
    Оценка:
    _W>Долго думал над группой, решил всё-таки в С++.
    Оба варианта не правильные, это вопрос организации работы группы. Просмотра кода, определения политик кодировани, где какие и почему исключения должны использоваться, итп... Без этих мер грабли будут и просто с возвратом кодов ошибок.
    ... << RSDN@Home 1.1.4 beta 4 rev. 303>>
    Народная мудрось
    всем все никому ничего(с).
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.