2009-05-04 5 views
18

Мне нужно использовать C для одного проекта, и я думаю использовать longjmp/setjmp для обработки ошибок, поскольку, по-моему, будет намного легче обрабатывать ошибки в одном центральном месте, чем коды возврата. Я был бы признателен, если есть какие-то выводы о том, как это сделать.Какие «хорошие» способы использовать longjmp/setjmp для обработки ошибок C?

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

Также как я обрабатываю ошибки, которые приводят к использованию многопоточных программ, использующих их?

Еще лучше, есть ли библиотека C, которая уже существует для обработки ошибок/исключений?

ответ

5

Я только что нашел один использовать для setjmp()/longjmp(), и это не было связано с обработкой ошибок.

На самом деле нет необходимости использовать его для этого, поскольку он всегда может быть реорганизован в нечто более легкое для подражания. Использование setjmp()/longjmp() очень похоже на goto тем, что его можно легко злоупотреблять. Все, что делает ваш код менее читаемым, является плохой идеей в целом. Обратите внимание, что я не говорю, что они изначально плохи, просто они могут привести к плохому коду проще, чем к альтернативам.

FWIW, одно место, в котором они были неоценимы, было проектом, который я делал в первые дни работы в отрасли (MS-DOS 6 временных рамок). Мне удалось собрать совместную многопоточную библиотеку с использованием Turbo C, которая использовала эти функции в функции yield() для переключения задач.

Я вполне уверен, что я не коснулся их (или не имел необходимости) с тех пор.

+1

+1 Я использовал их только один раз: в защите от копирования для DOS-игры. Я использовал longjmp вместо обычного разветвления, чтобы запутать крекеры. Это несколько сработало, потому что сгенерированный код выглядит как ничего, кроме ветки. :-) –

+0

Забавное совпадение: я построил кооперативную нитку ок. 1985, используя setjmp()/longjmp() для запуска на рабочей станции SGI под их уникальным вкусом дня. Работал как шарм. Так как он использовался для анимации, он включал rendevous, который синхронизировал все потоки с вертикальным прерыванием видеосистемы. Однако я не использовал их с тех пор. – RBerteig

5

Symbian реализовал механизм Leave с точки зрения longjmp(), и это служит хорошей прогулкой по всем вещам, которые вам нужно выполнить.

У Symbian есть глобальный «стек очистки», который вы нажимаете и нажимаете на вещи, которые хотите очистить, если произойдет прыжок. Это ручная альтернатива автоматическому отключению стека, которое компилятор C++ делает, когда генерируется исключение C++.

У Symbian были «ловушки для ловушек», из которых он выпрыгнул; они могут быть вложенными.

(Symbian недавно переопределил его в терминах исключений C++, но интерфейс не изменился).

В целом, я считаю, что правильные исключения на C++ менее подвержены ошибкам кодирования и намного быстрее, чем перенос собственного C-эквивалента.

(Современные компиляторы C++ отлично справляются с «нулевыми накладными расходами», если они не выбрасываются, например: longjmp() должен хранить состояние всех регистров и даже тогда, когда скачок не будет принят позже, поэтому можно принципиально никогда не бывало так же быстро, как исключения.)

Использование C++ как лучшего C, где вы используете только исключения и RAII, было бы хорошим путем, используя longjmp() для эмуляции исключения, заманчивой для вас.

+0

Пожалуйста, используйте правильное название: longjmp/setjmp, а не 'longjump'. –

+0

благодарит за информацию. Тем не менее, вопрос специфичен для использования C not C++ – dubnde

+0

@MeThinks, это прекрасно, мой совет применим к C; Я наметил симуляцию разворачивания стека (например, Cleanup Stack от Symbian) как то, как вы делаете очистку ресурсов, заданную в своем вопросе. – Will

0

Исключения - это, безусловно, лучший общий механизм, но в глубокие темные дни прошлого С, я написал эмулятор процессора, который включал командную оболочку. Оболочка, используемая для setjmp/longjmp для обработки прерываний (т. Е. Процессор работает и пользователь нажимает break/ctrl-c, код прерывает SIGINT и longjmps обратно в оболочку).

14

Если вы беспокоитесь о очистки ресурсов, вы должны серьезно задаться вопросом longjmp() и setjmp(), являются ли хорошей идеей.

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

+1

+1, потому что никто, кажется, не поднимает разумные ответы, которые не только слепо отвечают на вопрос – MatthewD

0

Я использовал setjmp/longjmp достаточно аккуратно, чтобы избежать изнутри обратного вызова, без необходимости обсуждать мой путь через различные уровни библиотеки.

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

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

Выполнение этого задания в контексте многопоточного программирования? Я уверен, что это не невозможно, но Ооо: вытащите свою семейную пачку аспирина. Вероятно, разумно держать пары setjmp/longjmp как можно ближе друг к другу. Пока соответствующая пара setjmp/longjmp находится в пределах одного потока, я ожидаю, что все будет в порядке, но ... будьте осторожны.

Смежные вопросы