Re[24]: Какие у исключений проблемы?
От: AlexRK  
Дата: 15.11.14 07:40
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Пока что все выглядит так, что я открываю Америку — деструкторы не должны возвращать ошибку, а все действия, которые могут ее вернуть, должны быть вызваны явно. По сути мы просто перекладываем всю логику обработки на программиста.


ARK>Но в этом свете хваленый RAII оказывается просто пшиком, потому что безошибочно с гарантией освободить можно только память.

ARK>Не, можно конечно просто плюнуть на полную корректность, как в С++ и поступают. "Подумаешь, файл не закрылся, этого почти никогда и не бывает."
ARK>Но для меня такой вариант неприемлем.

Не может ли уважаемый DarkEld3r пояснить, с чем он несогласен?
С тем, что любая операция освобождения ресурса (и даже операция записи в лог) хоть редко, но может завершиться с ошибкой? Или с тем, что проглатывать эти ошибки нехорошо?
Не срача ради, а токмо истины для.
Re[25]: Какие у исключений проблемы?
От: DarkEld3r  
Дата: 15.11.14 11:14
Оценка: +1
Здравствуйте, AlexRK, Вы писали:

ARK>Не может ли уважаемый DarkEld3r пояснить, с чем он несогласен?

Не согласен с подачей, а именно с "RAII оказывается просто пшиком". Да, деструкторы не панацея и не решение всех проблем. Да, в сложных случаях, надо писать дополнительный "ручной" код, но в общем, с ними всё равно удобнее.

ARK>>Не, можно конечно просто плюнуть на полную корректность, как в С++ и поступают.

Ок, как должен выглядеть правильный вариант?

Я уж не говорю о том, что даже если мы будем всегда сохранять все возникшие ошибки, то это не гарантирует их последующую корректную обработку. Кто помешает их просто игнорировать? Ну и раз мы в этой теме, то у кодов возврата такая же фигня, если не хуже (nested exception выглядит всё-таки удобнее).
Re[26]: Какие у исключений проблемы?
От: AlexRK  
Дата: 15.11.14 11:29
Оценка:
Здравствуйте, DarkEld3r, Вы писали:

DE>Да, в сложных случаях, надо писать дополнительный "ручной" код, но в общем, с ними всё равно удобнее.


Получается, что "простые случаи" — это когда мы просто игнорируем потенциальную ошибку.

ARK>>>Не, можно конечно просто плюнуть на полную корректность, как в С++ и поступают.

DE>Ок, как должен выглядеть правильный вариант?

В том-то и дело, что нормального варианта я не знаю.

Пока что у меня такое мнение: с точки зрения корректности, правильно всегда вызывать вручную все методы типа close и, в случае возникновения сбоя, передавать ошибку дальше (исключениями, кодами возврата или еще чем — неважно). Плюс система типов должна гарантировать вызов этих методов, чтобы нельзя было забыть их вызвать (хотя в С++ гарантировать это невозможно). Но идеальным такой вариант я назвать не могу.

DE>Я уж не говорю о том, что даже если мы будем всегда сохранять все возникшие ошибки, то это не гарантирует их последующую корректную обработку. Кто помешает их просто игнорировать?


Это уже другой вопрос. Что там наверху, мы не знаем и не хотим знать. Главное, что свой код у нас написан корректно.
Re[27]: Какие у исключений проблемы?
От: DarkEld3r  
Дата: 15.11.14 11:49
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Получается, что "простые случаи" — это когда мы просто игнорируем потенциальную ошибку.

Далеко не всегда это проблема.

ARK>Это уже другой вопрос. Что там наверху, мы не знаем и не хотим знать. Главное, что свой код у нас написан корректно.

А я-то думал, что главное — это корректность работы программы в целом.

ARK>Пока что у меня такое мнение: с точки зрения корректности, правильно всегда вызывать вручную все методы типа close и, в случае возникновения сбоя, передавать ошибку дальше (исключениями, кодами возврата или еще чем — неважно). Плюс система типов должна гарантировать вызов этих методов, чтобы нельзя было забыть их вызвать (хотя в С++ гарантировать это невозможно). Но идеальным такой вариант я назвать не могу.

Ну и получим при вызове функции кучу "ошибок" "не удалось записать в лог", например.

На мой взгляд, у ошибок всё-таки степень важности разная бывает. Некоторые можно и проигнорировать ("подумаешь файл не закрылся"). Вряд ли, возможна система типов которая правильно это будет "понимать" и заставлять обрабатывать.
Отредактировано 15.11.2014 11:55 DarkEld3r . Предыдущая версия .
Re[28]: Какие у исключений проблемы?
От: AlexRK  
Дата: 15.11.14 12:12
Оценка:
Здравствуйте, DarkEld3r, Вы писали:

ARK>>Получается, что "простые случаи" — это когда мы просто игнорируем потенциальную ошибку.

DE>Далеко не всегда это проблема.
DE>На мой взгляд, у ошибок всё-таки степень важности разная бывает. Некоторые можно и проигнорировать ("подумаешь файл не закрылся").

Все-таки, RAII это библиотечный код, как ни крути. И он за меня сразу принимает решение, что ошибки при финализации надо игнорировать. При этом он, вообще говоря, не знает, что действительно можно проигнорировать, а что нельзя. А потом поверх этого кода пишется тонна другого кода. В результате, если мне все-таки _надо_ среагировать на ошибку закрытия файла, то иного варианта, кроме как переписать вообще все это, не существует.

ARK>>Это уже другой вопрос. Что там наверху, мы не знаем и не хотим знать. Главное, что свой код у нас написан корректно.

DE>А я-то думал, что главное — это корректность работы программы в целом.

Это, конечно, главное.
Но причем тут стратегия работы с ошибками в самом низу? Наш код в большинстве случаев не знает, что делать с ошибкой. Он просто должен сообщить о ней наверх. А если мы ошибку всегда глотаем, то тем самым принимаем политическое решение, полномочий на которое у нас нет.

DE>Ну и получим при вызове функции кучу "ошибок" "не удалось записать в лог", например.


ИМХО, это лучше, чем не получить ничего и тихо-мирно работать дальше, не зная, что уже что-то пошло не так.
Хотя, конечно, это зависит от приложения.
Но сам подход "замалчивания" мне не нравится.

Я понимаю, что ошибки закрытия файлов или сетевых соединений довольно редкие и обычно их можно просто игнорировать. И что написана куча кода с RAII и он работает (?). Но сам фундамент этого подхода, ИМХО, ущербен (прошу прощения за эмоциональную "подачу" ).
Re[29]: Какие у исключений проблемы?
От: DarkEld3r  
Дата: 17.11.14 09:02
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Все-таки, RAII это библиотечный код, как ни крути. И он за меня сразу принимает решение, что ошибки при финализации надо игнорировать. При этом он, вообще говоря, не знает, что действительно можно проигнорировать, а что нельзя. А потом поверх этого кода пишется тонна другого кода. В результате, если мне все-таки _надо_ среагировать на ошибку закрытия файла, то иного варианта, кроме как переписать вообще все это, не существует.

Я всё-таки "спорил" в контексте этой темы. В смысле "исключения против кодов возврата". В таком случае, не вижу разницы. Вот есть у нас функция возвращающая Result<T, Error>. В итоге или мы будем возвращать ошибки вида "не удалось записать в лог", даже если результат был успешно получен. Или точно так же будем игнорировать "мелкие" ошибки.


ARK>Это, конечно, главное.

ARK>Но причем тут стратегия работы с ошибками в самом низу?
При том, что нет смысла в "идеальном" "сообщении об ошибках" если обработка их будет сложной и неудобной. И как удобно сделать обработку сразу кучи возникших ошибок я плохо представляю.
Re[30]: Какие у исключений проблемы?
От: AlexRK  
Дата: 17.11.14 10:44
Оценка: 1 (1)
Здравствуйте, DarkEld3r, Вы писали:

DE>Я всё-таки "спорил" в контексте этой темы. В смысле "исключения против кодов возврата". В таком случае, не вижу разницы.


Да, если в контексте темы, то никакой разницы нет.

ARK>>Но причем тут стратегия работы с ошибками в самом низу?

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

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


Прочел еще http://rsdn.ru/forum/dotnet/3856586.all
Автор: anton_t
Дата: 25.06.10
на ту же тему. Ничего интересного не обнаружил. Доставил пользователь с ником _FRED_, отказывающийся верить, что в дотнете многие методы Dispose кидают исключения.
Re[25]: Какие у исключений проблемы?
От: chaotic-good  
Дата: 17.11.14 15:11
Оценка: :)
Разницы между исключениями и кодами возврата быть не должно, до тех пор, пока количество ошибок пренебрежимо мало по сравнению с количеством успешных вызовов. Это происходит потому что в процессоре есть branch predictor, который успешно предсказывает ветвления при проверках кодов ошибок в 99.(9)% случаев. Если количество ошибок выелико, исключения работают медленнее чем коды ошибок по понятным причинам.

WH>Debug:

WH>No exceptions: 00:00:00.0254283 (1784293664), 00:00:00.0222134 (1784293664)
WH>Single exception: 00:00:00.0245588 (1785293665), 00:00:00.0232391 (1785293665)
WH>Two exceptions: 00:00:00.0242956 (1785293665), 00:00:00.0234590 (1785293665)

Забавно читать рассуждания о производительности, написаные любителями бенчмаркать дебажный(!sic) код
Re[26]: Какие у исключений проблемы?
От: chaotic-good  
Дата: 17.11.14 16:28
Оценка:
Здравствуйте, chaotic-good, Вы писали:

CG>Разницы между исключениями и кодами возврата быть не должно, до тех пор, пока количество ошибок пренебрежимо мало по сравнению с количеством успешных вызовов. Это происходит потому что в процессоре есть branch predictor, который успешно предсказывает ветвления при проверках кодов ошибок в 99.(9)% случаев. Если количество ошибок выелико, исключения работают медленнее чем коды ошибок по понятным причинам.


Иллюстрация:

#include <iostream>
#include <stdexcept>
#include <boost/timer.hpp>

volatile int K = 1000000000l - 1;

void check_value(int x) {
    if (x == K)
        throw std::runtime_error("invalid value");
}

bool check_value_ret(int x) {
    return x == K;
}

int main()
{
    boost::timer tm;
    size_t value = 0u;
    try {
        while(true) {
            check_value(value);
            value++;
        }
    }
    catch(const std::runtime_error& err) {
        double secs = tm.elapsed();
        std::cout << value <<  ", With exception: " << secs << std::endl;
    }
    value = 0u;
    tm.restart();
    while(true) {
        if (check_value_ret(value)) break;
        value++;
    }
    double secs = tm.elapsed();
    std::cout << value << ", Without exception: " << secs << std::endl;
    return 0;
}


999999999, With exception: 0.278302
999999999, Without exception: 0.271519


В примере выше, .NET компилятор просто фейлит оптимизацию более сложного кода с бранчами, поэтому для .NET возможно имеет смысл обратное.
Re[18]: Какие у исключений проблемы?
От: enji  
Дата: 22.11.14 15:43
Оценка:
Здравствуйте, Sinclair, Вы писали:

E>>Дык одно из исключений добавлять к основному. Проблема в плюсах в том, что можно выкинуть любой объект (очень интересно, зачем?).

S>Зачем как раз понятно — чтобы можно было "не платить за то, чего не используешь" — в случае чего прямо throw hr; catch(HRESULT).

исключения сами по себе недешевы, опять же, на самом деле к исключению добавляется информация о типе. Неясно, для чего сделали альтернативный механизм, отданный на откуп компиляторам (к которому доступа без хаков нет), а не обычный dynamic_cast.
Re[18]: Какие у исключений проблемы?
От: enji  
Дата: 22.11.14 15:44
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Вот смотри, у тебя задача скачать файл из сети по данному url'у. Понятно что по такой вроде бы просто формулируемой задаче мы имеем наверное больше десятка низкоуровневых ошибок (начиная с открытия сокета и заканчивая записью на диск). Теперь простой вопрос: что ты планируешь выдавать пользователю в данном случае? )


ну наверное описание ошибки — сервер не ответил, соединения разорвано, нет места на диске...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.