LINUX.ORG.RU

А как вы решаете зоопарк кодов возврата ошибки в си?

 


0

2

Скажем у вас есть проект А, в которым вы юзаете в разное время написанные B и C, а потом еще подключаете стороннюю библиотеку D.

По историческим причинам у них у всех разные коды возврата ошибки (например A_init_convo(type_t type) возвращает 342 в случае если сокет недоступен, или B_send_transmission(u8 * data, u32 size) вернет 24 если data = NULL).

Делаете ли какие-либо обертки? У нас, например, есть проект (который пока что без внешних зависимостей, только наши либы, у которого особым образом регистрируются коды ошибок с описанием (связка функций error_register + XMACRO).

★★★★★
Ответ на: комментарий от redgremlin

и перенумерую,

Но зачем? Чем вам номера то мешают? Чтобы сломать бинарную совместимость на пустом месте?

vodz ★★★★★
()

В проекте A – придумать свой нескучный способ передачи ошибок (мне нравится GError). Что касается библиотечных вызовов, то всегда лучше их обернуть в свой специфический API – велик шанс, что он окажется существенно проще, чем более универсальный библиотечный. Плюс, сегодня у тебя библиотека D, завтра ты найдёшь более крутую библиотеку F – менять проще, если вызовы D у тебя не валяются по всему проекту, а сидят в одной модульной единице.

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

Фигесе на ровном месте. По условиям задачи два или более проекта надо привести к единообразному виду. Это просто коды ошибок — весьма простая часть и ломается только ABI, доведись унифицировать интерфейсы и API переломается до неузнаваемости. а вообще, лично мне глубоко пофиг на ABI, я не пишу проприетарщину.

redgremlin ★★★★★
()

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

регистрируются коды ошибок с описанием (связка функций error_register + XMACRO).

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

Ну будет внешняя либа пусть с api в 100 функций, навешать обёртки можно за рабочие сутки ::)

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

Это просто коды ошибок — весьма простая часть и ломается только ABI

Ага, а вот смотри есть либа А её использует ваш проект B в котором есть либа С которая сама по себе тоже использует либу А и вот изменив коды возврата либы А для проекта B ты сломаешь логику в либе С потому что по кодам возврата внутри там выстроены if/else. И на ровном месте мы усложнаяем себе жизнь, сейчас не надо, в вот потом нужна будет либа С эта и что тогда? Лучше всё же обёртки или прямое внедрение в код.

Dron ★★★★★
()
Последнее исправление: Dron (всего исправлений: 1)
Ответ на: комментарий от redgremlin

По условиям задачи два или более проекта надо привести к единообразному виду. Это просто коды ошибок

Не наводите тень на плетень. Коммент был конкретно о перенумерации. Для приведения к единообразному виду перенумерация не нужна, нужно добавить единообразные коды, а там где получится принципиальные конфликты, там надо сделать обёртки.

vodz ★★★★★
()

зачем его решать

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

Все надеются, что это сделаешь ты. Пообещай мне, что лично выбросишь C. Надеюсь за тобой не заржавеет. :(

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

и вот изменив коды возврата либы А для проекта B ты сломаешь логику в либе С

Сфигали я что-то сломаю? Там как было if (ret_val == E_TIMEOUT) так и будет. А если в моей сборочной системе не предусмотрено, что при сборке проекта B компилировать и либу A и все её использующие, то мне надо менять профессию.

redgremlin ★★★★★
()
Последнее исправление: redgremlin (всего исправлений: 1)
Ответ на: комментарий от vodz

Для приведения к единообразному виду перенумерация не нужна

Даже если либа A использует #define E_NETWORK_UNREACHABLE 1488 , а либа B #define E_NETWORK_UNREACHABLE 666 ?

а там где получится принципиальные конфликты, там надо сделать обёртки

Ради нахрен ненужного сохранения ABI?

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

подожжи, подожжи, т.е. если твой проект будут компилировать с другой оригинальной версией либы вместо твоей с переименованными кодами ошибок, то всё поломается?

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

Даже если либа A использует #define E_NETWORK_UNREACHABLE 1488 , а либа B #define E_NETWORK_UNREACHABLE 666 ?

Конечно, вы почему используете A и B? Ведь наверняка A конектится по сети к одному, B - к другому, вот так и назовите каждую ошибку по своему, как-нибудь так:

#include <A>
static const int E_NETUNREACH_A=E_NETWORK_UNREACHABLE;
#undef E_NETWORK_UNREACHABLE
#include <B>
static const int E_NETUNREACH_B=E_NETWORK_UNREACHABLE;

Ради нахрен ненужного сохранения ABI?

Библиотеки же не ваши? Вы принципиально собираетесь создать проблемы пользователю?

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

Библиотеки же не ваши?

Скажем у вас есть проект А, в которым вы юзаете в разное время написанные B и C

Вы принципиально собираетесь создать проблемы пользователю?

Проприетарщикам? Да.

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

Проприетарщикам? Да.

Да господи, причём тут это? Если вы не сможете убедить авторов или А или B синхронизировать свои библиотеки по интерфейсу, то ваш «патч» по поводу замены констант создаст проблемы пользователям вашей проги, то есть вы и будете проприетарщиком, к которому будет привязан пользователь.

vodz ★★★★★
()
Последнее исправление: vodz (всего исправлений: 1)
Ответ на: комментарий от redgremlin

С какого перепою?

С такого. Если пользователь создась фичереквест на любую биюлиотеку, авторам оно понравятся и они выкатят новую версию, пользователю придётся идти на поклон к вам, чтобы вы милостливо подправили «патч».

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

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

vodz ★★★★★
()

Самая жесть, когда одни функции возвращают 0 в случае успеха, а другие — возвращают 0 в случае ошибки… А насчет ошибок, у меня есть свои уже давным-давно писанные обертки, которые присваивают одну глобальную переменную errno, чтобы следующим printf'ом или еще чем не сбросить, а далее выводят стандартными функциями.

Вот свои коды ошибок — да, либо дефайнами, либо енумами делаю, а текстовые описания — когда как. То const char**, то тупо по тексту..

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

Интеллигента видно издалека.

Отож.

Особенно такого, который не может хоть как-то обосновать свою позицию.

Вот уже и до откровенной лжи дошли. Ну так типичный ЛОР, хрен поймёшь, толи человек туп, толи он прикрывает этой тупостью свой факап. Но как бы ни было, никакого смысла писать по 10 раз и так и этак жевать одну мысль.

vodz ★★★★★
()
Ответ на: комментарий от i-rinat

Я обрадовался, думал хоть что-то с этим нашёл: e2fsprogs, оказалось и там не то, а свой аналог warnx/errx, как и в mc. nfsprogs в statd вот подключает include, но не юзает. Смех да и только.

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

Хорошо что вменяемым разработчикам популярных OSS библиотек не пофиг.

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

Да все тут половину кодов не проверяют, а остальные коды проверяют на != 0. Только коней сферических в теме изобретают.

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

Боярин, коды ошибок встраиваются в твой код и в (уже скомпиленую) шаред либу в виде чисел. Менять коды в уже скомпиленой либе не получится, а если ты сидишь не на генту, то вереницу синхронизации бинарных версий библиотек где постоянно ломается ABI поддерживать никто не будет.

dzidzitop ★★
()

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

очень редко бывают конфликты макросов в хэдерах. я с таким сталкивалась пару раз, когда макросы в библиотеках дублировали макросы в хэдерах ядра, например, или в крупных гнутых библиотеках. тогда я писала разработчикам и они меняли макросы. но это крайне редкие случаи, если раз в десять лет наткнёшься - это «повезло».

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

очень редко бывают конфликты макросов в хэдерах.

Не то чтобы «раз в 10 лет», но такое решается очень просто, разнести пофайлово работу с одной внешней библиотекой от другой. А иначе, зачем вы их обе взяли? Это же не libc-шные макросы, с которыми конфликтовать полный идиотизм. В конце концов, можно и поднять вопрос перед авторами библиотек, чтобы конфликты сгладить, на такое они вполне охотно пойдут, так как явно не по злому умыслу сделано и вообще-то стараются делать уникальные вещи.

vodz ★★★★★
()

код выше 255 вообще странно. Если надо регистрировать ошибки от всех подряд почему-бы не прибавлять к ответам А 1000 В 2000 С 3000 и т.д. тогда их можно хранить вместе и не путать.

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

бывает, что и libc-шные. ну или кернельные. было такое, например, на моей памяти: netsnmp конфликтовала с кернельным макросом. написала разработчику netsnmp - он пофиксил конфликт, переименовав макрос у себя. но это действительно редкость.

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

Iron_Bug ★★★★★
()
Последнее исправление: Iron_Bug (всего исправлений: 1)
Ответ на: комментарий от Iron_Bug

такие конфликты встречаются действительно редко

А, ну да, это у меня они постоянно, в busybox принято каждую апплету вставлять в виде: один файл - одна утилита. А вы попробуйте iptables в виде одного файла создать... Да там X-Macro сидит на X-Macro и друг друга погоняет и, сколько опций, столько как минимум help()/print(), каждый в своём файле изначально.

хорошей практикой является добавление префикса с именем библиотеки к глобальным макросам, которые видны во внешних хэдерах.

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

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

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

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

есть библиотеки, которые начинали писать лет 20 назад

Слава богу, из 30-летнего кода я мало что юзаю, ну разве что свой tetris и vagabondo как память.

чаще всего подобные конфликты возникают именно с очень старым кодом.

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

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

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

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