Является ли хорошей практикой программирования использовать setjmp и longjmp в C?
Я программист на С++ и использую языки OO с хорошей обработкой исключений.
Из того, что я могу понять, setjmp и longjmp - это, по сути, способ c-style для распространения исключений. Они также кажутся интенсивной формой goto, которая может рекламировать стек.
Итак, в первую очередь: хорошо ли использовать эти методы в прямом смысле C на данный момент времени, или они устарели? (примечание: C не С++).
Во-вторых, есть ли у них какое-либо использование в С++ или я правильно понимаю, что они были унаследованным механизмом, который был заменен функциями обработки исключений на С++?
Ответы
Ответ 1
По существу, вы правы в своем утверждении, что распространение jmp
-этапов по существу совпадает с goto
. Прочитайте Дейкстра (знаменитая и противоречивая) статья о goto
, которая (я думаю) дает разумные аргументы в пользу того, почему goto
редко следует использовать. Если вы точно не знаете, почему вы делаете то, что делаете (или работаете в очень специфических областях, таких как встроенное программирование), вы не должны касаться либо goto
, либо longjmp
.
Ответ 2
они используются для реализации сопрограмм. В сети есть несколько библиотек С++ coroutine, которые в Unix/Linux будут использовать setjmp/longjmp
для реализации функций.
Итак, если ваша цель - реализовать библиотеку coroutine, то это спорный вопрос, если его хорошая практика или нет, поскольку на этих платформах это единственный способ, чтобы поддерживать эту функциональность.
если ваша цель - использовать библиотеку сопрограмм, вам следует искать некоторые из них. Существует даже предложение ускоренного хранилища, называемое boost:: context, которое уже одобрено.
Ответ 3
Есть несколько правильных вариантов использования setjmp/longjmp
. Реализация сопрограммы с ними практически невозможна, так как вам нужно использовать (непереносимые) трюки (читай: встроенная сборка) для переключения стеков.
Одно использование setjmp/longjmp
заключается в том, чтобы поймать сигналы с плавающей запятой, но это испортило раскрутку стека С++. Исправьте C, хотя.
Вы также можете реализовать некоторую форму разворачивания стека (путем поддержки вашего собственного стека обработчика очистки) и реализовать с ними истинные деструкторы и исключения из C. Это очень удобно в крупных проектах: отсутствие правильного механизма обработки ошибок является слабым местом C. Однако, это довольно сложно сделать правильно, и вам нужно написать кучу макросов, чтобы облегчить задачу.
Ответ 4
Вы, конечно, не хотите использовать setjmp
в С++, как вы говорите, для чего нужны исключения. Вы не хотите использовать их в C, потому что это очень сложно. Постарайтесь найти другие решения.
Ответ 5
setjmp/longjmp - полезный способ реализовать собственную обработку исключений в чистом C. http://sourceware.org/pthreads-win32/announcement.html
Ответ 6
setjmp
и longjmp
- это макросы, используемые для обхода нормального вызова функции и обратного потока.
setjmp
сохраняет вызывающий env, который будет использоваться longjmp
Правильное использование этих макросов действительно сложно, и вы можете легко в итоге выполнить undefined.
Из-за этого, как правило, требуется ограничить longjmp
до 1 уровня обработчика сигнала (лучше всего вообще не называть).
В критических системах требуется не использовать вообще.