Исключения против errno

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

В чем принципиальная разница между исключениями и использованием errno?


person Philip    schedule 13.05.2011    source источник
comment
Довольно просто: игнорировать исключение вполне допустимо, даже если это желательно. У него отличное определенное поведение.   -  person Hans Passant    schedule 13.05.2011


Ответы (6)


Здесь так много различий, что сложно сказать, с чего начать.

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

Исключения C ++ автоматически разворачивают стек вызовов, пока не найдут функцию, подготовленную для обработки ошибки. Это означает, что в большинстве случаев пользователям не нужно явно проверять каждый вызов на наличие ошибок; вместо этого они могут собирать отчеты об ошибках в одном месте. Исключения C ++ могут содержать значения, отличные от целых, в отличие от errno.

person Conrad Meyer    schedule 13.05.2011

Вы можете случайно проигнорировать errno. Необходимо иметь дело с исключениями.

Конечно, я видел свою долю:

try {
   // something
}
catch( ... ) {
   // nothing
}
// continue as if nothing happened

и (Java)

try {
   // something
}
catch( Throwable t ) {
   // nothing
}
// continue as if nothing happened

НО по крайней мере это как бы выскакивает на вас, когда вы боретесь с чужим беспорядком.

person Andrew    schedule 13.05.2011

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

person rlduffy    schedule 13.05.2011

1) Исключение может быть любым, а не только целым числом. Итак, данные передаются разные.

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

person Steve Jessop    schedule 13.05.2011

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

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

person Timo Geusch    schedule 13.05.2011

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

  pkt_type = tcp_getbyte(my_stream, timeout);
  pkt_length = tcp_getbyte(my_stream, timeout);
  pkt_length |= tcp_getbyte(my_stream, timeout) << 8;
  if (pkt_length < MAX_PACKET_LENGTH)
  {
    for (i=0; i<pkt_length; i++)
      buffer[i] = tcp_getbyte(my_stream, timeout);
  }
  if (!my_stream->error)
  {
    /* Do something with packet */
  }

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

person supercat    schedule 13.05.2011