LINUX.ORG.RU

[C] [жизнь без исключений] Как вы обрабатываете ошибки?

 


0

0

Пишу на C прошивку для микроконтроллера. Возникла следующая проблема:

while (1) {
	..
	for (..) {
		..
		if (..) {
			вдруг неожиданно произошло что-то очень не хорошее, например, аппаратная ошибка несовместимая с нормальной работой программы, нужно выйти из цикла while (1)
		}
		..
	}
	..
	switch (..) {
	case ..:
		if (..) такая же ситуация...
		break;
		..
	}
	..
}
.. 
if (флаг если ошибка) {
	обработка
}
..

И как тут быть? Неужели goto, и будет мне вагон счастья? А как же «напишешь «goto» и за тобой придёт бабай! Буууу!» (c), Дейкстра и весь такой прочий антураж?


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

> Ребёнок, когда, наконец-таки, научишься читать -- сходи в библиотеку и возьми умных книжек.

Прикол в том, что он читал умные книги... но "дурака учить - только портить" (c)

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

> Прикол в том, что он читал умные книги... но "дурака учить - только портить" (c)

Понимаешь, в чём проблема... Есть такой классический пример:
-- Ты урок выучил?
-- Я учииил...

Он свою писанину прочесть и понять-то не может, а ты про умные книжки. Сначала ему нужно просто научиться читать, и только потом эти книги открывать. Первый пункт пропускать вредно, но ему это невдомёк.

kemm
()
Ответ на: комментарий от chicane

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

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

>Он свою писанину прочесть и понять-то не может, а ты про умные книжки.

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

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

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

хотя для данного кода у меня есть вариант с исключениями как try:

<something>

except something: return -1

except something: return -1

finally: <free resources>

(синтаксис питоновский)

chicane
()
Ответ на: комментарий от true_admin

> С эсепшенами лоханулся, согласен. Думал можно сделать, но у меня толкового кода не вышло.

т.е. такой код даже в C++ надо писать с goto? А если в языке нет goto (типа Java)?

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

>Я все разлодил по полочкам и даже описал как нужно реализовывать такие функции.

ну это уже не смешно даже...

chicane
()
Ответ на: комментарий от kemm

я знаю, ты явно нет - не передёргивай. Прочитай ещё раз свой пост про break и мой ответ. Долго думай. Сходи к старшему товарищю, может объяснит. Hint: Логический блок это не {} :)))

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

>Я говорю, мне надоело объяснять - хочешь, почитай.

так читал же, в отличии от вас, не нашел ваших умных объяснений :)

chicane
()
Ответ на: комментарий от golodranez

>Голословные утверждения здесь были только со стороны любителей гото. Я все разлодил по полочкам и даже описал как нужно реализовывать такие функции. Если тебе чтото, то я здесь не причём.

по-моему вы привели только один (недоделанный) пример с копипастой. еще один пример привел lester, заменивший goto на do-while-break, что собственно этим же goto и осталось, только без ненависного слова.

если я что-то просмотрел, дайте ссылки на свои разложенные по полочкам функции.

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

> Сходи к старшему товарищю

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

kemm
()
Ответ на: комментарий от chicane

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

ладно, в этом споре я участие заканчиваю, а то так можно до бесконечности:)

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

> еще один пример привел lester

точнее два - еще вариант с выносом частей кода, которые могут оборвать вычисления в отдельные функции, и вызовом как:

bool success =
open( name ) &&
link( path ) &&
read( buf ) &&
...

// Clean
if( !success )
{
}

это ес-но для С, а не С++

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

>Код будет недлиннее и читабельней.

ваш код показал обратное

>В реальном приложении почти никогда не получится так, чтобы последовательность меток была нужна.

ваш код показал обратное

also: какие реальные приложения вы разрабатывали?

chicane
()
Ответ на: комментарий от kemm

>Умения читать и понимать прочитанное

Радует слышать такое от человека, который не знает элементарных понятий программирования и не может понять, что я написал :)

>а не только в IT (куда тебе, впрочем, путь заказан)

сынок, профиль открой))

На этом всё.

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

>ваш код показал обратное ваш код показал обратное

тебе показалось. моего кода здесь вообще небыло. Был код топик стартера без гото. Прочитай ещё раз что я написал.

Всё, меня здесь нет. А то всю еду тролям уже отдал:) Это я не про тебя.

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

> break и continue завершают всегда логические блоки, в отличии от goto. Дети, вы задолбали уже фигню писать.

Правильно, break и continue *всегда*, goto *не*всегда. Но судя по комментариям, все согласны, не использовать goto в стиле 80-ых, а только в тех же рамках, что и break, continue, т.е. локально, исключительно в пределах одной функции, и не для трюков в алгоритмах, а для лучшей структуры программы. Так что если вы не против continue, break, то, значит, не должны были бы быть против goto (в выше приведенном контексте!).

Часто упоминаете работодателя. Говорит о том, что первая его мысль при виде goto стандартна: ага, не умеет программировать по современным стандартам. При этом даже после демонстрации локальности goto сохраняет сомнения: сегодня он локально goto использует, а завтра обленится и пойдет-поедет, лучше от него избавиться еще сегодня. Такая *теория* у меня насчет вашей неприязни к использованию goto.

Насчет goto метка это копипаст - нет, это не так, так как метки разные (в приведенных примерах). А close(fd) - да, потому что именно эта комманда с параметрами повторяется 1:1.

Читаемость читаемостью, но поддержка важнее, к тому же неявно подразумевает читаемость. Если я в пример с сокетами куда-нибудь добавлю еще одну операцию, а потом мне надо будет по всему коду далее добавлять соотв. close(), то легко где-нибудь да пропустить это. В случае же с циклом for(;;){...break;...} или ему эквивалентный метод с локальным goto, я иду в конец функции, где производится последовательное освобождение ресурсов, и добавляю один раз новое close(). Все.

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

> Вот когда будете участвовать в больших проетках, тогда расскажите)

прелесть какая. поучи поучи, дам еще сальца.

покажешь чем отличается goto с пачкой меток от такой же пачки catch? про ресурсы я уж не говорю.

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

> все согласны, не использовать goto в стиле 80-ых

Ну вот не надо клеветать на 80-е :) Как правильно использовать goto, было ясно уже в 70-х. В начале :)

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

Ты уже переписал ту функцию без goto и гор копипасты? Вперёд, балаболка.

kemm
()
Ответ на: комментарий от golodranez

>тебе показалось. моего кода здесь вообще небыло.

нас всех так старательно плющит с твоей недоделаной колбасой из копипаст, гордо именуемой кодом?

chicane
()
Ответ на: комментарий от gag

>Насчет goto метка это копипаст - нет, это не так, так как метки разные (в приведенных примерах). А close(fd) - да, потому что именно эта комманда с параметрами повторяется 1:1.

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

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

> Ну вот не надо клеветать на 80-е :) Как правильно использовать goto, было ясно уже в 70-х. В начале :)

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

Но смысл в том, что goto goto рознь. Конечно, проще вообще не использовать - так не ошибиться, когда хорошо, а когда плохо :)

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

> добавим выделение памяти - всюду появится free(mem).

И lester прав, к каждому free(mem) еще и mem = NULL.

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

> который не знает элементарных понятий программирования

Ещё раз: не проецируй своё невежество на окружающих.

> и не может понять, что я написал

Ты сам-то понимаешь, что пишешь? То, что ты не умеешь читать и понимать написанное другими -- заметили уже все.

> сынок, профиль открой))

Открыл, внучок:

> "Оснавная рабочая деятльность"

Оно и видно, что быдлокодишь ты примерно на том же уровне, как и по-русски пишешь. Хоть один проект-то в пример приведёшь? А то "разработчик и внедренец хеллоу-ворлдов" мало интересен.

kemm
()
Ответ на: комментарий от golodranez

> Я все разлодил по полочкам и даже описал как нужно реализовывать такие функции.

еще раз: ты предлагаешь сделать close(fd) несколько раз. берем и добавляем еще один дескриптор. что теперь, править весь код?

это так вы, всей конторой, пишите «большие проекты»? скажи хоть как контора называется, страна должна знать своих героев.

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

>> Это из серии "гладко было на бумаге".

> что не так?

Возвращаемые функциями результаты не запоминаются и не обрабатываются. IRL такого не бывает.

> и как бы вы поступили при написании такого: http://www.linux.org.ru/jump-message.jsp?msgid=3937702&cid=3939711

Скорее всего, так: http://www.linux.org.ru/jump-message.jsp?msgid=3937702&cid=3941627

Только я бы не брал goto err_* в {} - это напрасная трата места.

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

> Возвращаемые функциями результаты не запоминаются и не обрабатываются. IRL такого не бывает.

ну чуть упростил, было бы так:

bool success =
open( fd, name ) &&
link( fd, path ) &&
read( fd, buf ) &&
...

небольшая разница

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

> т.е. такой код даже в C++ надо писать с goto?

надо, чтобы вложенных блоков было меньше.

if(!BoxReadParams(box)) { showError (); return }
if(params->virt) { showError (); return }
if(!Logon(hw,&lg)) && (!Pop3Enter(login,password)) { showError(); return }


и т.д. как минимум. т.е. получится просто толпа проверок и после нее
уже код загрузки этих самых писем.

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

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

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

Если тебе в функции надо открывать кучу файлов, то нафиг такую функцию, думай и переписывай. Тоже с памятью.

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

ЗЫ Тролям и неучу kemm не отвечаю:) Пусть слюной дальше брызжут.

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

ну кстати вот и я накасячил.

|| вместо &&, конечно.

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

> небольшая разница

Потому что возвращаемые значения не обрабатываются.

int r1, r2, r3;

r1 = f1();
r2 = f2();
r3 = f3(r1 + r2 + 1);

Вытянешь это в цепочку? Считаем, что f[1-3] возвращают отрицательный код ошибки при провале (не обязательно -1), и этот код нужно вернуть наверх.

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

> а какже:

охты, да. по недосмотру. я почему-то решил что оно вызывается на каждый «else».

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

В ООП-языках вообще надо писать по-другому, поэтому goto в них или нет или он нежелателен. Высвобождением ресурсов занимаются gardage collector и деструкторы объектов, поэтому зачастую можно выкинуть эксепшн а остальное на себя возьмёт техника. Поэтому код будет совершенно другой. А тут сишный код. C++ != C.

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

>if(!BoxReadParams(box)) { showError (); return }
>if(params->virt) { showError (); return }

>if(!Logon(hw,&lg)) && (!Pop3Enter(login,password)) { showError(); return }


И тут несколько точек выхода, что ж за любовь такая к return?

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

> Я не предлагаю писать close(fd)

серьезно?

тут какой-то м^Hчудак написал вот это: http://www.linux.org.ru/jump-message.jsp?msgid=3937702&cid=3939277

не знаешь кто?

> напиши нормальную программу, чтобы не пришлось так извращаться.

вот именно, тебя уже которую страницу просят...

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

что в вашем понятии, "нормальная программа"? Может все таки goto?

chicane
()
Ответ на: комментарий от golodranez

>Если тебе в функции надо открывать кучу файлов, то нафиг такую функцию, думай и переписывай. Тоже с памятью.

ок. хочу открыть сокет, поймать клиента, прочитать, записать в файл. на сколько функций разбить? спроектируй?

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

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

Идиот, предложи другой способ открыть unix domain socket. Влезло чудо, которое стандартных вещей в глаза не видело, и поэтому узнать их неспособно. Мир состоит не только из "Hello, world!", сю-ю-ю-юрпри-и-и-из!

> ЗЫ Тролям и неучу kemm не отвечаю:) Пусть слюной дальше брызжут.

Да все и без того заметили, что сказать по делу тебе нечего, только бредить способен. Даже простейшую функцию не смог переписать.

kemm
()
Ответ на: комментарий от lester

> может не так понял, но:

Ты понял правильно, но смошенничал с ответом. Функции принимаю на вход столько аргументов, сколько написал я, а не ты. Код врапперов ты не привел.

>bool success = >res = f1( r1 ) >= 0 && >res = f2( r2 ) >= 0 && >res = f3( r3, r1 + r2 + 1) >= 0;

И ты считаешь это нормально написанным фрагментом кода? O_o Тут как минимум желание повыпендриваться знанием приоритетов операций (я их не проверял, но ты сам-то в правильности уверен?). Да, и зачем нужна переменная success?

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