Pull to refresh

Comments 11

Запоздалая, но полезная статья.

От себя добавлю, что error_category::message не обязывает возвращать константную строку. Возможны прокси-категории, скажем, для группировки ошибок по типам, локализации, преобразования кодировок (привет Microsoft), конструирование сообщений на лету и многое другое.

Из-за того, что message возвращает std::string вместо const char*, пришлось отказаться от этого удобного способа обработки ошибок на микроконтроллере. Сильно напрягает по ресурсам, когда их мало.

все стандартные контейнеры позволяют переопределять аллокатор

И что это даст? Всё равно останется аллокация и копирование. А текст описания ошибки в подавляющем числе случает вполне себе вписывается в рамки const char*.

Спасибо за наводку. Прочту на днях, как раз сам сейчас пытаюсь вникнуть во все тонкости темы.
Возможно, переведу и эти статьи. Или, быть может, уже кто-то перевел?

P.S.: Забавно, что этот автор тоже ссылается на переведенный здесь цикл.

Увы, у технологии есть и минусы:


  1. При сравнении error_code и error_condition делается минимум один виртуальный вызов, если они эквивалентны, и минимум два, если нет. Это дорого.


  2. В libstd++ (стандартная библиотека C++ на debian) между версиями 3.4.18 и 3.4.21 есть проблемы с совместимостью. Если такие два теста собрать на Ubuntu Trusty, а запустить на Ubuntu Xenial, первый выдаст неверный результат, а второй упадёт.

С такими минусами, в частности, столкнулись в LLVM и обходят их так:
https://github.com/llvm-mirror/llvm/commit/803fe1968007aa7a9c4f9674af648c9840f02a11
https://github.com/llvm-mirror/llvm/blob/master/include/llvm/Support/Errc.h

Согласен, технология дорогая. Но за удобство абстракций всегда приходится платить, верно?

А вот накладку в реализации стандартной библиотеке сложно относить к минусам именно самой технологии. Кстати, спасибо что поделились этой информацией, не находил упоминаний об этом ранее.
Лично мне кажется, что это не те абстракции, за которые я хотел бы платить. Мне вполне достаточно статического отображения платформозависимых кодов в платформонезависимые, и не каждый раз при каждом сравнении, а один раз, при первом их появлении. Дальше можно сравнивать коды по значению, писать `switch`-и и это будет дёшево.

Ситуаций, где мне потребовалось бы явно работать с платформозависимыми кодами вне платформенных обёрток, я стараюсь не допускать. Остаётся платформозависимое описание ошибки, которое нужно протащить через платформонезависимый код. Вот для него виртуальный вызов вполне адекватен, но и без него можно было бы просто протащить необрабатываемый char* (правда, его пришлось бы вычислять нелениво).

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

В одной из своих статьей Страуструп писал:
> In general, C++ implementations obey the zero-overhead principle: What you don’t use, you don’t pay for. And further: What you do use, you couldn’t hand code any better.

Для разработчиков LLVM и для меня это место так не выглядит. Но интересно было бы увидеть примеры активного расширения system_error в настоящих проектах (boost предлагать не надо).

Думаю, всё сильно зависит от частоты вызовов.

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

Скажем, "не удалось открыть файл" - если он там ожидается ВСЕГДА, и ошибка прямо относится к исключительным ситуациям (например, закончилось место на диске, или отвалилась сетевая шара) - трудно представить, когда в этой ситуации надо экономить такты. А если закончилась память - то там вообще "мы все падаем, аааа!"

В общем, всё зависит от того, что считать ошибками. Этот путь должен быть исключительно редким, тогда ничего экономить не нужно.

Sign up to leave a comment.

Articles