LINUX.ORG.RU

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

 


0

0

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

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

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


В ядре используют goto и не краснеют.

Deleted
()

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


неужели "аппаратная ошибка несовместимая с нормальной работой программы" отловится по if() ? ))) есть ли в С конструкции вида try { } catch { } ?
если нет, и если ошибка действительно критическая, программа сама вылетит.
если же таки ошибка такая что можно отловить по if (), то 1. нужно выйти именно из цикла while() ? или из (под)программы? exit() там есть? ) 2. зачем тогда выходить? может быть лучше сделать функцию-обработчик и тупо вызывать её по условию?

isden ★★★★★
()

Аппаратную ошибку оператором if() не обработаешь. Для защиты от таких случаев используют сторожевой таймер(Watchdog Timer), который предназначен для предотвращения блокировки системы при сбоях и зависаниях программы.

smoke_man
()

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

ты и миллионы леммингов не понимают о чем писал Дикстар.

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

> неужели "аппаратная ошибка несовместимая с нормальной работой программы" отловится по if()

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

> 1. нужно выйти именно из цикла while() ? или из (под)программы? exit() там есть? ) 2. зачем тогда выходить? может быть лучше сделать функцию-обработчик и тупо вызывать её по условию?

По сути нужно выйти из подпрограммы до этого сделав некоторые действия. Хотя, таки вариант в каждом таком if делать что-то типа do_error1_handler(); do_finally(); return;

Спасибо, попробую...

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

> ты и миллионы леммингов не понимают о чем писал Дикстар.

Возможно. Разъясни научно-популярно.

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

> И как тут быть?

Разбить твою мегапортянку на функции, которые возвращают код ошибки.

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

>Возможно. Разъясни научно-популярно.

Дейкстра говорил о том, что нужно избегать goto любой ценой, но не ценой ясности программы. И таки да, в системном программировании обработка ошибок через goto error самая обычная практика. Тут как раз недавно это обсуждали=)

dizza ★★★★★
()

Вообще-то, не очень хорошо так писать. Правильнее сделать основным рабочим циклом while(1){}; , а все остальное - по прерываниям (таймер использовать), каждое событие отрабатывает отдельная функция. Соответственно, если произошла ошибка - выход из функции с возвратом кода ошибки.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от dizza

> таки да, в системном программировании обработка ошибок через goto error самая обычная практика. Тут как раз недавно это обсуждали=)

И ведь всё равно нашлись же снобы, которые осуждали goto %)

P.S. а исключения всё равно лучше.

tailgunner ★★★★★
()

Э-э-э... longjmp?

Хотя вообще-то, вложенность while->for->if->... не говорит об очень хорошем дизайне.

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

>Э-э-э... longjmp?

Угу. В виде
#define GOSUB setjmp(jmp);
#define RETURN if (jmp) longjmp(jmp);

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

> И ведь всё равно нашлись же снобы, которые осуждали goto %)

В С, вообще-то, можно обойтись без goto, просто надо тщательно обдумать алгоритм. Поэтому-то классики и не рекомендуют использовать эту команду.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

В жизни, вообще-то, можно обойтись без женщин, просто надо тщательно онанировать. Поэтому-то классики и не рекомендуют использовать женщин.

Silver bullet (в виде одной парадигмы) не существует.

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

>P.S. а исключения всё равно лучше.
а процессоры уже поддерживают исключения? или они всё так же сгенерять прерывание, которое вызовет обработчик

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

>> P.S. а рестарты всё равно лучше.

> Исправил досадную очепятку.

Не, рестарты не нужны. Умерла - значит, умерла.

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

> а процессоры уже поддерживают исключения?

Зависит от того, какой смысл ты вкладываешь в слово "исключение".

> или они всё так же сгенерять прерывание, которое вызовет обработчик

Держите меня трое... O_o

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

>Держите меня трое... O_o
обращение по неправильному адресу это исключительная ситуация? что происходит с процессором в этом случае?

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

> обращение по неправильному адресу это исключительная ситуация? что происходит с процессором в этом случае?

Какое отношение это имеет к языку программирования?

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

> обращение по неправильному адресу это исключительная ситуация?

Да. Только эти исключения никого не интересуют. Речь о встроенных в язык механизмах обработки исключительных ситуаций, которые реализуются по-другому.

> что происходит с процессором в этом случае?

Это экзамен? Лучше подумай, что будет, если все исключения буду обрабатываться подобным образом.

tailgunner ★★★★★
()

Чтото я вообще вижу повода использовать тут goto. И вообще таких поводов не существует:)

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

>И таки да, в системном программировании обработка ошибок через goto error самая обычная практика.

мля, не надо так делать!

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

>В жизни, вообще-то, можно обойтись без женщин, просто надо тщательно онанировать. Поэтому-то классики и не рекомендуют использовать женщин.

В Си всегда можно обойтись без goto, если ты можешь хорошо продумать алгоритм. И в 100% решение без goto будет лучше.

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

>Да. Только эти исключения никого не интересуют.
ну тогда я ретировался, да постыдно

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

> В Си всегда можно обойтись без goto, если ты можешь хорошо продумать алгоритм.

В жизни можно обойтись без женщин, если ты можешь хорошо подготовиться к жизни без женщин.

> И в 100% решение без goto будет лучше.


И больше по объёму. И сложнее для прослеживания пути выхода по какому-то конкретному случаю.

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

>И больше по объёму. И сложнее для прослеживания пути выхода по какому-то конкретному случаю.

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

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

>по объёму может быть немного больше. Но по прослеживанию пути выхода нет ничего более жопного, чем goto. Если вы применяете goto - значит с вашим алгоритмом чтото не впорядке.

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

имхо, не стоит ставить субъективную красоту алгоритма и досканальное проектирование каждой мелочи во главу угла. путь goto это и не "круто", зато эффективно.

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

>Если вы применяете goto - значит с вашим алгоритмом чтото не впорядке.

Слишком общее заявление. На рассуждения Дейкстры или например Вирта конечно влиял трудный опыт использования goto в древних подмножествах Фортрана. Но как это все относится к языку Си где goto используется в основном для выхода из глубоко вложенных блоков при возникновении ошибки или встречается в аутпутах генераторов кода типа yacc не совсем ясно.

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

> Но по прослеживанию пути выхода нет ничего более жопного, чем goto.

А... так ты его просто готовить не умеешь.

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

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

Сам понял что сказал?))

if([error])
{
   error_code = [some_code];
   MakeErrMess(bla_bla);
   return -1;
}

goto не нужет вообще.

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

>Но как это все относится к языку Си где goto используется в основном для выхода из глубоко вложенных блоков

А теперь расскажи откуда взялись _глубоко_ вложенные блоки?

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

>>Но как это все относится к языку Си где goto используется в основном для выхода из глубоко вложенных блоков

>А теперь расскажи откуда взялись _глубоко_ вложенные блоки?

for (x = 0; x < ... ; x ++) {
  for (y = 0; y < ... ; y ++) {

  }
}

Absurd ★★★
()

При правильном проектировании такое что нужно топикстартеру вообще никогда не понадобиться.

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

и?

тебе по условию нужно закончить оба цикла? так пропиши эти условия в for() - код будет хорошо читаться. Напишешь там хоть один goto и буз бутылки уже не разберёшься.

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

>Сам понял что сказал?))

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

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

for (x = 0; x < ... && !fucked; x ++) {
  for (y = 0; y < ... && !fucked; y ++) {
     if (error)
       fucked = 1;
  }
}

for (x = 0; x < ... ; x ++) {
  for (y = 0; y < ... ; y ++) {
     if (error)
        goto get_out;
  }
}
get_out:

Ну и что проще?

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

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

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

В первом варианте ты забыл break.

Проще безусловно первый вариант. НО - см выше что я написал.

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

> Ну и что проще?

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

if( func1() && func2() )
{
...
}

// а тут был бы ненужный get_out

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

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

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

>тебе по условию нужно закончить оба цикла? так пропиши эти условия в for() - код будет хорошо читаться.

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

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

>или вы любой break заменяете return'ом?

Если в функции произошла ошибка, то безусловно при правильно проектировании будет return; break применяется для изменения поведения цикла при определённых условиях. если же тебе туго без goto, то сильно задумываешься, а потом переписываешь нафиг эту часть программы.

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

Т.е. ты предлагаешь все ошибки обрабатывать одним goto? А в логах сам потом разбираться будешь?:)) Сообщения об ошибках у тебя всеравно должны быть разные для каждого типа ошибки.

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

У меня это делаеться один раз при возникновении ошибки, с гото это будет КУЧА меток с куччей обработчиков _в конце функции_ :)))

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