LINUX.ORG.RU

Можно ли избежать дублирования кодов ошибок в С?


0

1

Пишу несколько либ, которые потом используются в общем проекте, но могут, естественно, линковаться и по-отдельности. В каждой есть свой набор кодов ошибок, многие из которых, однако, пересекаются. Например, часто встречается что-то вроде CORRUPT_MESSAGE, OUT_OF_MEMORY и т.п. Есть ли стратегия, позволяющая избежать дублирования кодов ошибок?

В порядке дискуссии, может вообще стоит перейти на более продвинутую обработку ошибок, вроде метода OpenSSL, setjmp/longjmp или еще чего-нибудь?


Ты можешь выделить общее подмножество кодов ошибок в ещё одну дополнительную «либу» (которая может состоять только из заголовочных файлов).

Deleted
()

Ну так и используй единые коды везде, где ошики одинаковые. А для либо-специфичных кодов отдельный диапазон.

UVV ★★★★★
()
Ответ на: комментарий от UVV

Ну это получается еще один errno.h. И так вводится дополнительная зависимость, что не сильно хорошо.

gaga
() автор топика
Ответ на: комментарий от crowbar

Я смотрел glib, но там как-то уж очень громоздко это сделано. И оно больше нужно чтобы передать ошибку на несколько уровней выше, чем чтобы упростить обработку кодов ошибок.

gaga
() автор топика
Ответ на: комментарий от UVV

нет, но там есть какое-то довольно общее множество. Придется тогда для кажого набора модулей выбирать общие ошибки, или как? Получится в идеале для трех либ ошибки в семи хедерах: lib1, lib2, lib3, lib12, lib13, lib23, lib123. А если их больше?

gaga
() автор топика

где можно, используй стандартные EXXXXXX из errno.h. Где не хватает - пиши свои коды, и да, можешь вынести их в отдельную утилитарную либу, либо не париться с этим и объявлять их в проектах. Имена дефайнов должны иметь префикс либы, так что проблема конфликтующих имён не возникнет. Чтобы новые коды ошибок гарантированно не совпадали с таковыми из errno.h, можешь делать 4-байтные коды ошибок таким макаром: http://git.videolan.org/?p=ffmpeg.git;a=blob;f=libavutil/error.h;h=f3fd7bbff6...

Krieger_Od ★★
()

Нужно ли? Если библиотеки что-то делают похожее и их можно представить похожими интерфейсами, то тогда имеет смысл делать и общие ошибки в виде другой библиотеки с описанием интферфейсов.

Иначе от этого будет больше гемора, ~ придётся следить за раздачей приватных диапазонов ошибок каждой либе, либо всё смешивать в кучу. В последнем случае будет неудобно понимать какие из ошибок могут возникнуть в конкретной библиотеке и из-за чего. Например, CORRUPT_MESSAGE может иметь различную смысловую нагрузку в разных либах. Чем меньше вариантов может вернуть конкретная ф-я и чем проще это увидеть (например, через небольшой enum), тем удобнее будет работать с либой.

Особенно дурацкая идея смешивать высокоуровневые ошибки либы с низкоуровневыми из с errno.h

mashina ★★★★★
()
Последнее исправление: mashina (всего исправлений: 1)

Ну и пусть пересекаются. Ты же знаешь, из какого множества ты ловишь.

esandmann
()
Ответ на: комментарий от Krieger_Od

хорошая идея c MKTAG, спасибо. Пожалуй, примерно так и буду делать.

gaga
() автор топика
Ответ на: комментарий от Krieger_Od

По ссылке. Я что-то от жизни отстал, как работает сей кусок кода? Что за фигня в {0}? Или используется какой-то дополнительный препроцессор?

static inline char *av_make_error_string(char *errbuf, size_t errbuf_size, int errnum)
{
     av_strerror(errnum, errbuf, errbuf_size);
     return errbuf;
}

#define av_err2str(errnum) \
     av_make_error_string((char[AV_ERROR_MAX_STRING_SIZE]){0}, AV_ERROR_MAX_STRING_SIZE, errnum)

vtVitus ★★★★★
()

Я бы сделал как в VirtualBox.

А как сделано там? А там используется COM, и поэтому механизм обработки ошибок взят виндовый, даже на платформах отличных от винды(используется XPCOM).

А как сделано в винде? А в винде все давно унифицировано и стандартизировано - т.е. это HRESULT + HRESULT_FROM_WIN32() для системных кодов ошибок. Плюс FormatMessage(строка берется из MessageTable, которые можно делать в т.ч. в своих dll/exe, в секции ресурсов).

lovesan ★★★
()
Ответ на: комментарий от UVV

Спасибо КЭП!!!

Мне больше интересно, что такое и как работает

(char[AV_ERROR_MAX_STRING_SIZE]){0}
и почему локальный буфер возвращают в return.

А то «Работает так, как надо» это просто тру ответ какой-то :-)

vtVitus ★★★★★
()
Ответ на: комментарий от vtVitus

ну создаёт на стеке вызывающей функции массив чаров, и инициализирует его. массивы инициализируются фигурными скобками. а неинициализированные элементы инициализируются нулём

anonymous
()
Ответ на: комментарий от lovesan

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

gaga
() автор топика

Ну, во первых, либа может выдавать не просто код ошибки, а ещё какой-то идентификатор самой либы (например, имя и версию).

Можно при загрузке выдавать либам базовые номера и внутри каких-то диапазонов они будут относительно этих базовых номеров выдавать свои ошибки. Я так делала при загрузке самодельных плагинов, количество которых было заранее неизвестно, но это нужно быть уверенным, что либа не вылезет за предел некоторого диапазона. Либо, если количество библиотек заранее известно, сделать эти диапазоны статическими и прописать где-то в заголовке.

Вообще, обычно привязка ошибок идёт не столько к либам, сколько к потокам. Проблему составляет, в основном, выяснение, кто вызвал ошибку.

Ну и какбэ если «часто встречаются» CORRUPT_MESSAGE, OUT_OF_MEMORY - может, надо что-то делать с кодом? Конечно, если это не особенность софта, который работает в каких-нибудь экстремальных условиях.

Iron_Bug ★★★★★
()
Ответ на: комментарий от Iron_Bug

CORRUPT_MESSAGE, OUT_OF_MEMORY - может, надо что-то делать с кодом?

С кодом надо что-то делать, если проверки на эти ошибки там нет =)

gaga
() автор топика
Ответ на: комментарий от gaga

Кстати, можно вместо нудной обработки в куче мест заюзать нечто типа http://code.google.com/p/exceptions4c/. Это обработка эксепшнов в С, на основе jmp_buf, setjmp и longjmp. Бесплатная библиотека.

Iron_Bug ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.