L'ho digitato in google ma ho trovato solo howtos in C ++,
come si fa in C?
L'ho digitato in google ma ho trovato solo howtos in C ++,
come si fa in C?
Risposte:
Non ci sono eccezioni in C. In C gli errori vengono notificati dal valore restituito dalla funzione, dal valore di uscita del processo, dai segnali al processo ( Segnali di errore del programma (GNU libc) ) o dall'interruzione hardware della CPU (o altra notifica errore dalla CPU, se presente) ( come il processore gestisce il caso di divisione per zero ).
Le eccezioni sono tuttavia definite in C ++ e in altri linguaggi. La gestione delle eccezioni in C ++ è specificata nello standard C ++ "Gestione delle eccezioni S.15", non esiste una sezione equivalente nello standard C.
main
in un .c
file può includere un po 'di C ++, e quindi le eccezioni potrebbero essere lanciate e catturate nel programma, ma le porzioni di codice C rimarranno all'oscuro di tutto ciò che accade tranne che il lancio e la cattura di eccezioni spesso si basano su funzioni scritte in C che risiedono nelle librerie C ++. C viene utilizzato perché non puoi rischiare che la funzione chiamata throw
debba lanciare un'eccezione stessa. Tuttavia, potrebbe esserci un modo specifico per compilatore / libreria / destinazione per generare / rilevare eccezioni. Ma lanciare un'istanza di classe avrà i suoi problemi.
In C puoi usare la combinazione delle funzioni setjmp()
e longjmp()
, definita in setjmp.h
. Esempio 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: in realtà ti consiglierei di non usarli poiché funzionano male con C ++ (i distruttori di oggetti locali non verrebbero chiamati) ed è davvero difficile capire cosa sta succedendo. Restituisci invece una sorta di errore.
if()
. Non ci vedo pericolo; qualcun altro qui?
Il vecchio C normale non supporta effettivamente le eccezioni in modo nativo.
È possibile utilizzare strategie di gestione degli errori alternative, come:
FALSE
e utilizzando una last_error
variabile o una funzione.Vedi http://en.wikibooks.org/wiki/C_Programming/Error_handling .
GetLastError()
nell'API di Windows.
Non esiste un meccanismo di eccezione integrato in C; è necessario simulare le eccezioni e la loro semantica. Questo di solito si ottiene facendo affidamento su setjmp
e longjmp
.
Ci sono parecchie librerie in giro e ne sto implementando un'altra ancora. Si chiama exceptions4c ; è portatile e gratuito. Puoi dare un'occhiata e confrontarlo con altre alternative per vedere quale si adatta di più.
C è in grado di generare eccezioni C ++, sono comunque codici macchina. Ad esempio, in 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
in 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;
}
per compilarlo
gcc -o bar.o -c bar.c && g++ a.cc bar.o && ./a.out
produzione
good 1976
http://mentorembedded.github.io/cxx-abi/abi-eh.html contiene informazioni più dettagliate su__cxa_throw
.
Non sono sicuro che sia portabile o meno e lo provo con "gcc-4.8.2" su Linux.
_ZTII
significa typeinfo for long
, ad es echo '_ZTIl' | c++filt
. È lo schema di mutilazione g ++.
Questa domanda è super vecchia, ma mi sono imbattuto in essa e ho pensato di condividere una tecnica: dividere per zero o dereferenziare un puntatore nullo.
La domanda è semplicemente "come lanciare", non come catturare, o anche come lanciare un tipo specifico di eccezione. Anni fa ho avuto una situazione in cui dovevamo attivare un'eccezione da C per essere catturati in C ++. In particolare, abbiamo avuto rapporti occasionali di errori di "chiamata di funzione virtuale pura" e dovevamo convincere la funzione _purecall del runtime C a lanciare qualcosa. Quindi abbiamo aggiunto la nostra funzione _purecall divisa per zero e boom, abbiamo ottenuto un'eccezione che potevamo catturare in C ++ e persino usare un po 'di stack divertente per vedere dove le cose sono andate storte.
Su Win con MSVC c'è __try ... __except ...
ma è davvero orribile e non vuoi usarlo se puoi evitarlo. Meglio dire che non ci sono eccezioni.
C non ha eccezioni.
Ci sono varie implementazioni hacker che cercano di farlo (un esempio su: http://adomas.org/excc/ ).
Come menzionato in numerosi thread, il modo "standard" di farlo è usare setjmp / longjmp. Ho pubblicato un'altra soluzione simile su https://github.com/psevon/exceptions-and-raii-in-c Questa è, per quanto ne so, l'unica soluzione che si basa sulla pulizia automatica delle risorse allocate. Implementa smartpointer unici e condivisi e consente alle funzioni intermedie di far passare le eccezioni senza intercettarle e di ripulire adeguatamente le risorse allocate localmente.
C non supporta le eccezioni. Puoi provare a compilare il tuo codice C come C ++ con Visual Studio o G ++ e vedere se verrà compilato così com'è. La maggior parte delle applicazioni C verrà compilata come C ++ senza grandi modifiche, quindi è possibile utilizzare la sintassi try ... catch.
Se scrivi codice con Happy path design pattern (cioè per dispositivi embedded) puoi simulare l'elaborazione degli errori di eccezione (aka deffering o finalmente emulazione) con l'operatore "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;
}
In realtà non gestisce le eccezioni, ma ti offre un modo per gestire l'errore all'uscita dalla funzione.
PS Dovresti fare attenzione a usare goto solo dagli stessi o più ambiti profondi e non saltare mai la dichiarazione delle variabili.