Quais são algumas das “boas” maneiras de usar longjmp / setjmp para manipulação de erros C?

StackOverflow https://stackoverflow.com/questions/819864

Pergunta

Eu tenho que usar C para um projeto e estou pensando em usar longjmp/setjmp para o tratamento de erros, como eu acho que vai ser muito mais fácil de erro de identificador em um lugar central do que códigos de retorno. Eu apreciaria se existem algumas pistas sobre como fazer isso.

Estou particularmente preocupado com a limpeza de recurso que está sendo feito corretamente se ocorrer qualquer erro.

Também como faço para lidar com os erros que resultam em programas multi-threaded usando eles?

Mesmo melhor, há alguma biblioteca C que já existe para erro de manipulação / exceção?

Foi útil?

Solução

Tenha um olhar para este exemplo / tutorial:
http://www.di.unipi.it/~nids/docs/longjump_try_trow_catch .html

Outras dicas

Se você está preocupado com a limpeza dos recursos, você tem que seriamente se perguntam se longjmp () e setjmp () são uma boa idéia.

Se você projetar seu sistema de alocação de recursos para que você possa, de fato, limpar com precisão, então é OK - mas que o projeto tende a ser complicado e, normalmente incompleto se, de fato, as bibliotecas padrão que seus próprios usos de código alocar recursos que devem ser liberados. Ele requer um cuidado extraordinário, e porque não é totalmente confiável, não é adequado para sistemas que possam ter necessidade de sobreviver usos múltiplos do setjmp () / longjmp () chamadas de longa duração (eles vão vazar, expandir e, eventualmente, causar problemas).

Symbian implementou do mecanismo Leave em termos de longjmp() e isso serve como uma boa caminhada através de todas as coisas que você precisa fazer.

Symbian tem uma 'pilha de limpeza' global que você empurra e coisas pop que você quer limpar deve um salto aconteceu. Esta é a alternativa manual para a pilha automática descontrair que compilador de C ++ que quando uma exceção de C ++ é lançada.

Symbian tinha 'arreios Trap' que iria saltar para; estes poderiam ser aninhados.

(Symbian reimplemented mais recentemente, em termos de exceções C ++, mas a interface permanece inalterada).

Todos juntos, eu acho que as exceções adequada C ++ são menos propensas a erros de codificação e muito mais rápido do que rolar seus próprios C equivalente.

(compiladores Modern C ++ são muito bons em exceções 'de zero gerais' quando não são jogados, por exemplo; longjmp() tem de armazenar o estado de todos os registros e tal, mesmo quando o salto não é depois levado, pode assim, fundamentalmente, nunca mais ser tão rápido como exceções.)

Usando C ++ como um melhor C, onde você só adotar exceções e RAII, seria uma boa rota deve usar longjmp() para emulação de exceção ser tentador para você.

Só tenho alguma vez encontrado um uso para setjmp()/longjmp() e não era a ver com manipulação de erro.

Não há realmente nenhuma necessidade de usá-lo para que, uma vez que sempre pode ser reformulado em algo mais fácil de seguir. O uso de setjmp()/longjmp() é muito semelhante ao goto em que ele pode ser facilmente abusado. Tudo o que faz o seu código menos legível é uma má idéia em geral. Note que eu não estou dizendo que eles são inerentemente ruim, apenas que eles podem levar ao mau código mais fácil do que as alternativas.

FWIW, o único lugar que eles foram inestimáveis ??era um projeto que eu fiz nos primeiros dias da indústria (MS-DOS quadro 6 tempo). Eu consegui montar uma biblioteca de multi-threading cooperativo usando Turbo C que usou essas funções em uma função yield() para alternar as tarefas.

Estou bastante certo de que eu não toquei-los (ou tinha a necessidade de) desde aqueles dias.

As exceções são, de longe, um melhor mecanismo geral, mas nos dias escuros profundos de C passado, escrevi um emulador de processador, que incluiu um shell de comando. O invólucro utilizado para setjmp / longjmp para tratamento de interrupções (isto é, o processador está rodando e os acessos dos utilizadores quebrar / CTRL-C, o código intercepta SIGINT e longjmps de volta ao reservatório).

Eu usei setjmp / longjmp razoavelmente arrumada, para escapar de dentro de um retorno de chamada, sem ter de negociar meu caminho até através de vários outros níveis da biblioteca.

Esse caso (se bem me lembro) foi onde um código dentro de um analisador gerado pelo yacc poderia detectar um problema (não-sintática), e queria abandonar o parse, mas dar uma volta relatório de erro razoavelmente útil para o chamador sobre o outro lado de todo o código gerado pelo yacc. Outro exemplo foi dentro de um callback chamado de um analisador Expat. Em cada caso, havia outras maneiras de fazer isso, mas eles pareciam mais complicada e obscura do que simplesmente resgatando desta forma.

Como outras respostas têm para fora pontas, porém, é necessário ter cuidado com a limpeza, e muito pensativo sobre certificando-se de que o código longjmp é exigível apenas no âmbito da região protegida de forma dinâmica pelo setjmp.

fazê-lo no contexto da programação de multi-threaded? Tenho certeza de que não é impossível, mas Oooh: sair a sua família pacote de aspirina agora. É provavelmente sábio para manter os pares setjmp / longjmp tão próximas quanto possível. Enquanto um par setjmp correspondência / longjmp estão dentro do mesmo segmento, espero que você vai ser OK, mas ... ter cuidado lá fora.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top