2010-05-23 18 views
62

Escribí esto en google pero solo encontré howtos en C++,Cómo lanzar una excepción en C?

cómo hacerlo en C?

+6

C no admite el manejo de excepciones. Para lanzar una excepción en C, debe usar algo específico de la plataforma como el manejo estructurado de excepciones de Win32, pero para brindar ayuda con eso, necesitaremos conocer la plataforma que le interesa. –

+14

... y no use el manejo de excepciones estructurado de Win32. –

+2

Usar setjmp() y longjmp() debería, en teoría, funcionar, pero no creo que valga la pena. –

Respuesta

44

No hay excepciones en C. En C los errores son notificados por el valor devuelto de la función, el valor de salida del proceso, las señales al proceso (Program Error Signals (GNU libc)) o la interrupción del hardware de la CPU (u otro error de notificación CPU si la hay) (How processor handles case of division by zero).

Excepciones definidas en C++ y otros lenguajes. El manejo de excepciones en C++ se especifica en el estándar C++ "Manejo de excepciones S.15", no hay una sección equivalente en el estándar C.

+2

Entonces en C está garantizado que no habrá excepciones, ¿cómo? – httpinterpret

+0

@httpinterpret: si tiene el código C, entonces no hay forma de lanzar una excepción como la que está pensando. Es más probable que obtengas un código de retorno o que caigas en algún código que tenga un comportamiento indefinido. –

+39

@httpinterpret: en C está "garantizado" que no hay excepciones de la misma manera que está "garantizado" que no hay plantillas, ni reflejos, ni unicornios. La especificación del lenguaje simplemente no define tal cosa. Sin embargo, hay setjmp/longjmp, que se puede usar para salir de una función sin regresar. De modo que los programas podrían construir sus propios mecanismos de excepción si así lo desean, o una implementación C podría definir extensiones al estándar. –

6

C no tiene excepciones.

Existen varias implementaciones de Hacky que intentan hacerlo (un ejemplo en: http://adomas.org/excc/).

18

La antigua C no admite excepciones de forma nativa.

Puede utilizar estrategias alternativas de tratamiento de errores, tales como:

  • devolver un código de error
  • regresar FALSE y el uso de una función de variable o last_error.

Ver http://en.wikibooks.org/wiki/C_Programming/Error_handling.

3

C no admite excepciones. Puede intentar compilar su código C como C++ con Visual Studio o G ++ y ver si se compilará como está. La mayoría de las aplicaciones de C compilarán como C++ sin grandes cambios, y luego puedes usar la sintaxis try ... catch.

5

En Win con MSVC hay _try ... __except ... pero es realmente horrible y no quiere usarlo si es posible evitarlo. Es mejor decir que no hay excepciones.

+0

En realidad, las excepciones de C++ se basan en la parte superior del SEH también debajo del capó. – Calmarius

25

En C puede usar la combinación de las funciones setjmp() y longjmp(), definidas en setjmp.h. Example from 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: que en realidad le aconsejaría no para usarlos en su trabajo horrible con C++ (destructores de objetos locales no consiguen llamada) y es realmente difícil de entender lo que está pasando en. Devuelve algún tipo de error en su lugar.

+0

He visto que setjump/longjump no funciona correctamente en los programas C++ incluso cuando no hay objetos que necesitan destrucción cuando se usan excepciones. Raramente los uso en programas C. – nategoose

+0

Este fue un enfoque interesante usando setjmp. http://www.on-time.com/ddj0011.htm Pero sí, básicamente tienes que inventarlos tú mismo si quieres la ejecución de código fuera de banda sin desenrollar la pila. –

+0

No estoy seguro de por qué la advertencia sobre el uso de ellos en C++ cuando la pregunta es acerca de C y C++ tiene excepciones de todos modos. En cualquier caso, es importante que el OP sepa que para evitar que la implementación de setjmp/longjmp le dispare, siempre tenga en cuenta que primero debe visitar el controlador de errores (para configurarlo).), y ese controlador de errores debe devolver dos veces. –

14

No hay mecanismo de excepción incorporado en C; necesita simular excepciones y su semántica. Esto generalmente se logra confiando en setjmp y longjmp.

Hay bastantes bibliotecas alrededor, y estoy implementando otra más. Se llama exceptions4c; es portátil y gratis. Puede echarle un vistazo y compararlo con other alternatives para ver cuál le conviene más.

+0

+1 para proporcionar un enlace a su biblioteca ** y ** un enlace a las alternativas. – Barzee

5

Esta pregunta es muy antigua, pero me topé con ella y pensé en compartir una técnica: dividir por cero o eliminar la referencia de un puntero nulo.

La pregunta es simplemente "cómo tirar", no cómo atrapar, o incluso cómo lanzar un tipo específico de excepción. Tuve una situación hace años en la que necesitábamos activar una excepción de C para capturarla en C++. Específicamente, tuvimos informes ocasionales de errores de "pura llamada de función virtual", y necesitábamos convencer a la función _purecall del tiempo de ejecución C para que arrojara algo. Así que agregamos nuestra propia función _purecall que se divide por cero, y boom, obtuvimos una excepción que pudimos captar en C++, e incluso usamos un poco de diversión para ver dónde salieron las cosas mal.

3

Como se menciona en numerosos hilos, la forma "estándar" de hacer esto es usar setjmp/longjmp. Publiqué otra solución similar a https://github.com/psevon/exceptions-and-raii-in-c Según tengo entendido, es la única solución que depende de la limpieza automática de los recursos asignados. Implementa smartpointers únicos y compartidos, y permite que las funciones intermedias permitan el paso de excepciones sin captura y aún así se limpien adecuadamente los recursos asignados localmente.

8

C es capaz de lanzar C++ excepción, son códigos de máquina de todos modos. Por ejemplo, en 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 

en 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; 
} 

compilarlo

gcc -o bar.o -c bar.c && g++ a.cc bar.o && ./a.out 

salida

good 1976 

http://mentorembedded.github.io/cxx-abi/abi-eh.html tiene más detalle Info aproximadamente __cxa_throw.

No estoy seguro de si es portátil o no, y lo pruebo con 'gcc-4.8.2' en Linux.

Cuestiones relacionadas