Eu digitei isso no google, mas só encontrei howtos em C ++,
como fazer em C?
Eu digitei isso no google, mas só encontrei howtos em C ++,
como fazer em C?
Respostas:
Não há exceções em C. Em C os erros são notificados pelo valor retornado da função, o valor de saída do processo, sinais para o processo ( sinais de erro do programa (GNU libc) ) ou a interrupção do hardware da CPU (ou outra notificação erro da CPU, se houver) ( Como o processador trata o caso de divisão por zero ).
As exceções são definidas em C ++ e outras linguagens. O tratamento de exceções em C ++ é especificado no padrão C ++ "Tratamento de exceções S.15", não há seção equivalente no padrão C.
main
em um .c
arquivo pode incluir algum C ++ e, portanto, exceções podem ser lançadas e capturadas no programa, mas as partes do código C permanecerão ignorantes de tudo isso, exceto que o lançamento e a captura de exceções geralmente dependem de funções escritas em C que residem nas bibliotecas C ++. C é usado porque você não pode arriscar que a função chamada throw
precise lançar uma exceção. Pode haver uma maneira específica do compilador / biblioteca / destino para lançar / capturar exceções, no entanto. Mas lançar uma instância de classe terá seus próprios problemas.
Em C, você pode usar a combinação das funções setjmp()
e longjmp()
, definidas em setjmp.h
. Exemplo da Wikipedia
#include <stdio.h>
#include <setjmp.h>
static jmp_buf buf;
void second(void) {
printf("second\n"); // prints
longjmp(buf,1); // jumps back to where setjmp
// was called - making setjmp now return 1
}
void first(void) {
second();
printf("first\n"); // does not print
}
int main() {
if ( ! setjmp(buf) ) {
first(); // when executed, setjmp returns 0
} else { // when longjmp jumps back, setjmp returns 1
printf("main"); // prints
}
return 0;
}
Nota: Eu realmente aconselharia você não usá-los porque eles funcionam muito mal com C ++ (destruidores de objetos locais não seriam chamados) e é realmente difícil entender o que está acontecendo. Em vez disso, retorne algum tipo de erro.
if()
. Não consigo ver perigo nisso; mais alguém pode aqui?
O C simples e antigo não suporta exceções nativamente.
Você pode usar estratégias alternativas de tratamento de erros, como:
FALSE
e usando uma last_error
variável ou função.Consulte http://en.wikibooks.org/wiki/C_Programming/Error_handling .
GetLastError()
na API do Windows.
Não há mecanismo de exceção embutido em C; você precisa simular exceções e sua semântica. Isso geralmente é conseguido confiando em setjmp
elongjmp
.
Existem algumas bibliotecas por aí, e estou implementando mais uma. É chamado de exceptions4c ; é portátil e gratuito. Você pode dar uma olhada nele e compará-lo com outras alternativas para ver qual se encaixa mais em você.
C é capaz de lançar a exceção C ++, eles são códigos de máquina de qualquer maneira. Por exemplo, em bar.c
// begin bar.c
#include <stdlib.h>
#include <stdint.h>
extern void *__cxa_allocate_exception(size_t thrown_size);
extern void __cxa_throw (void *thrown_exception, void* *tinfo, void (*dest) (void *) );
extern void * _ZTIl; // typeinfo of long
int bar1()
{
int64_t * p = (int64_t*)__cxa_allocate_exception(8);
*p = 1976;
__cxa_throw(p,&_ZTIl,0);
return 10;
}
// end bar.c
em a.cc,
#include <stdint.h>
#include <cstdio>
extern "C" int bar1();
void foo()
{
try{
bar1();
}catch(int64_t x){
printf("good %ld",x);
}
}
int main(int argc, char *argv[])
{
foo();
return 0;
}
para compilá-lo
gcc -o bar.o -c bar.c && g++ a.cc bar.o && ./a.out
resultado
good 1976
http://mentorembedded.github.io/cxx-abi/abi-eh.html tem mais informações detalhadas sobre__cxa_throw
.
Não tenho certeza se é portátil ou não, e testei com 'gcc-4.8.2' no Linux.
_ZTII
significa typeinfo for long
, por exemplo echo '_ZTIl' | c++filt
. É o esquema de mutilação g ++.
Esta pergunta é muito antiga, mas acabei de topar com ela e pensei em compartilhar uma técnica: dividir por zero ou remover a referência de um ponteiro nulo.
A questão é simplesmente "como lançar", não como pegar, ou mesmo como lançar um tipo específico de exceção. Tive uma situação há muito tempo em que precisávamos acionar uma exceção de C para ser detectada em C ++. Especificamente, tivemos relatórios ocasionais de erros de "chamada de função virtual pura" e precisávamos convencer a função _purecall do tempo de execução C a lançar algo. Então, adicionamos nossa própria função _purecall, que é dividida por zero, e bum, tivemos uma exceção de que poderíamos pegar em C ++ e até mesmo usar um pouco de diversão de pilha para ver onde as coisas deram errado.
No Win com MSVC existe, __try ... __except ...
mas é realmente horrível e você não vai querer usá-lo se puder evitá-lo. Melhor dizer que não há exceções.
C não tem exceções.
Existem várias implementações de hacky que tentam fazer isso (um exemplo em: http://adomas.org/excc/ ).
Conforme mencionado em vários tópicos, a maneira "padrão" de fazer isso é usando setjmp / longjmp. Postei outra solução desse tipo em https://github.com/psevon/exceptions-and-raii-in-c. Que eu saiba, essa é a única solução que depende da limpeza automática dos recursos alocados. Ele implementa smartpointers exclusivos e compartilhados e permite que funções intermediárias deixem as exceções passarem sem serem detectadas e ainda tenham seus recursos alocados localmente limpos de forma adequada.
C não oferece suporte a exceções. Você pode tentar compilar seu código C como C ++ com Visual Studio ou G ++ e ver se ele compilará como está. A maioria dos aplicativos C compilará como C ++ sem grandes alterações, e você pode usar a sintaxe try ... catch.
Se você escrever código com o padrão de design de caminho feliz (ou seja, para dispositivo embutido), você pode simular o processamento de erro de exceção (também conhecido como adiamento ou finalmente emulação) com o operador "goto".
int process(int port)
{
int rc;
int fd1;
int fd2;
fd1 = open("/dev/...", ...);
if (fd1 == -1) {
rc = -1;
goto out;
}
fd2 = open("/dev/...", ...);
if (fd2 == -1) {
rc = -1;
goto out;
}
// Do some with fd1 and fd2 for example write(f2, read(fd1))
rc = 0;
out:
//if (rc != 0) {
(void)close(fd1);
(void)close(fd2);
//}
return rc;
}
Na verdade, ele não faz o handler de exceção, mas mostra uma maneira de lidar com o erro na saída da função.
PS Você deve ter cuidado ao usar goto apenas em escopos iguais ou mais profundos e nunca saltar declaração de variável.