Перейти к содержанию
    

Ошибки функций... и последствия

Даже не знаю, как обозвать тему :)

 

Все что угодно соединяется. Выдается ID

вызываем функцию, которая в канал связи или пытается передать, или пытается получить оттуда

но что-то не получилось

Функция вернет ошибку (или количество байт не то, которое ждали)

 

Таких вызовов много

 

Как правильно сделать одну секцию ошибок, которая сделает (в зависимости от ошибки) одно действие, или несколько секций кода для разных ошибок?

 

Как это правильно делается, дабы каждый раз не плодить условий при вызове функций обмена?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я к чему

Обойтись можно средствами C или только C++ (try, catch, throw)?

Как удобнее .....?

мда.. отклик соседней ветки

 

 

Привычка делать на C рождает вопросы :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Обойтись можно средствами C или только C++ (try, catch, throw)?

Как удобнее .....?

Привычка делать на C рождает вопросы :)

Все равно независимо от использования С или С++ Вы переберете все ошибки, которые хотите обработать. Разница, насколько я помню, в том, что в С Вы должны заранее задать все ошибки и их обработать, с необработанными Вы сами решите, как поступать; а в С++ есть механизм передачи необработанных ошибок в объект-родитель, можете добавить обработчики в объект-родитель. Как будет короче - виднее только Вам.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Все равно независимо от использования С или С++ Вы переберете все ошибки, которые хотите обработать. Разница, насколько я помню, в том, что в С Вы должны заранее задать все ошибки и их обработать, с необработанными Вы сами решите, как поступать; а в С++ есть механизм передачи необработанных ошибок в объект-родитель, можете добавить обработчики в объект-родитель. Как будет короче - виднее только Вам.

объекта-родителя НЕТ

есть просто функция, которая _может_ возвратить некоторую ошибку

хрошо, с кодами ошибок и с описаниями для пользователя - не вопрос

как (и можно ли) это сделать на C ?

это, фактически, вопрос не только к билдеру, но и к embedded, типа 32flash и 4-8RAM

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

объекта-родителя НЕТ

есть просто функция, которая _может_ возвратить некоторую ошибку

хрошо, с кодами ошибок и с описаниями для пользователя - не вопрос

как (и можно ли) это сделать на C ?

это, фактически, вопрос не только к билдеру, но и к embedded, типа 32flash и 4-8RAM

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

да понятно, что функция что-то вернет, с обработкой тоже

ну не ваять же каждый раз

 

if (send2channel(structure, sizeof(structure)) != sizeof(structure)) goto _l_fullass;

 

или

if (send2channel(structure, sizeof(structure)) == FULLASS) goto _l_fullass;

 

потому как дальше нет смысла что-то делать

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, обработка ошибок на каком-то этапе неизбежно упирается в лень программиста :)

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

да понятно, что функция что-то вернет, с обработкой тоже

ну не ваять же каждый раз

 

if (send2channel(structure, sizeof(structure)) != sizeof(structure)) goto _l_fullass;

 

или

if (send2channel(structure, sizeof(structure)) == FULLASS) goto _l_fullass;

 

потому как дальше нет смысла что-то делать

Это Вы ваяете в вызываемой функции, тут все равно, какой язык.

 

С трассировкой вызовов

 

===============

send2channel (...)

{

...

if (received_counter != requested_counter) return ERROR_PACKET_SIZE;

...

}

 

caller_send2channel (...)

{

if (!send2channel(...)) handle_error (*from_caller, *error_queue и прочее)

}

==========

 

Это если есть трассировка цепочки вызовов.

 

Так как бы Вы хотели обработать ошибку, каким обработчиком-то? Или хотите, чтобы компилятор все сам сделал?

 

Все равно придется придумать механизм трассировки вызовов и отката назад по ошибкам. Это может быть отдельный модуль, может быть обработчик в вызывающей функции, все равно. Что С, что С++ без разницы. Такое ИМХО.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

На С++ это делается через механизм exception'ов (try/catch/throw), на С через пару setjump/longjmp

 

И в том и другом языке будут большие проблемы с локальными ресурсами - их будет некому освобождать. На С++ это частично можно победить с помощью RAII, на С простых методов увы нет :(

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

но думаю что это даст пищу для размышления.

 

если совсем по уму, то немного постулатов.

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

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

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

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

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

6) вся методология и технология применения противодействия эксепшенам должна:

1) как можно меньше зависить от человеческого фактора, в идеале создаваться на автомате.

2) быть простой в использовании.

3) правила применения не должны иметь двоякие толкования либо разночтения.

 

 

ну, где то так.

удачи вам

(круглый)

ЗЫ

Что касамое МК - в зависимости от специфики бывает по разному. Но как правило удобны системы содержащие постоянные каналы для контроля узлов и функционирования программы, железа. При этом фиксироваться должны все координаты: привязка к коду, данным, времени, версии сырцов, параметрам окружения.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Даже не знаю, как обозвать тему :)

 

Все что угодно соединяется. Выдается ID

вызываем функцию, которая в канал связи или пытается передать, или пытается получить оттуда

но что-то не получилось

Функция вернет ошибку (или количество байт не то, которое ждали)

 

Таких вызовов много

 

Как правильно сделать одну секцию ошибок, которая сделает (в зависимости от ошибки) одно действие, или несколько секций кода для разных ошибок?

 

Как это правильно делается, дабы каждый раз не плодить условий при вызове функций обмена?

 

Судя по тому, что Вы описали, Вам достаточно одной пары setjmp/longjmp. Функция типа FATAL(int ErrID) может вызываться откуда угодно. Если при этом работает куча - тут нада думать, прежде всего о том, чтобы таког о безобразия там не было. Удачи.

ЗЫ Тут еще недавно поминали конструкцию на похожий случай.

Изменено пользователем _Pasha

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поясню

 

Есть функция (точнее - несколько), в которых осуществляется передача данных путем вызова функций libusb

Каждый раз приходится их вызывать и контролировать количество принятых/переданных данных к заявленным к приему/передаче

Дабы сохранить читаемость, получается if, после которого есть goto на лабель, где сообщается ошибка и вываливаемся из функции

Такой подход (проверка каждого вызова функций приема/передачи и переход в одно и то же место) - нормально, или есть более красивые механизмы?

Пока вот смотрю в сторону исключений

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да нормально вполне, если не ошибаюсь, например, в OpenCV именно такой подход используют.

Как вариант (уже выше предложили похожее) вместо

goto crash_label;

писать

return crash_handler(чего-нибудь);

ИМХО симпатичнее, чем в конце функции писать, да и религиозная ненависть к goto удовлетворена :)

Это в embedded. На ББ предпочитаю C# и, естественно, исключения, но это уже совсееем другой разговор.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Такой подход (проверка каждого вызова функций приема/передачи и переход в одно и то же место) - нормально, или есть более красивые механизмы?

Пока вот смотрю в сторону исключений

Видимо, ссыль из моего пред. поста Вас не зацепил. Зря, чесслово! На машине Даффа строится отличная альтернатива исключениям, мсм.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...