J'ai tapé ceci dans google mais je n'ai trouvé que des howtos en C ++,
comment le faire en C?
J'ai tapé ceci dans google mais je n'ai trouvé que des howtos en C ++,
comment le faire en C?
Réponses:
Il n'y a pas d'exceptions en C.En C, les erreurs sont notifiées par la valeur renvoyée de la fonction, la valeur de sortie du processus, les signaux au processus ( Signaux d'erreur de programme (GNU libc) ) ou l'interruption matérielle du processeur (ou autre notification erreur de la CPU s'il y en a) ( Comment le processeur gère le cas de division par zéro ).
Les exceptions sont définies en C ++ et dans d'autres langages. La gestion des exceptions en C ++ est spécifiée dans la norme C ++ "S.15 Exception handling", il n'y a pas de section équivalente dans la norme C.
main
dans un .c
fichier peut inclure du C ++, et donc des exceptions peuvent être levées et interceptées dans le programme, mais les parties de code C resteront ignorantes de tout cela, sauf que le lancement et la capture d'exceptions reposent souvent sur des fonctions écrites en C qui résident dans les bibliothèques C ++. C est utilisé car vous ne pouvez pas risquer que la fonction appelée do throw
doive lever une exception elle-même. Il peut cependant y avoir un moyen spécifique au compilateur / bibliothèque / cible de lancer / intercepter des exceptions. Mais lancer une instance de classe aura ses propres problèmes.
En C, vous pouvez utiliser la combinaison des fonctions setjmp()
et longjmp()
, définies dans setjmp.h
. Exemple de 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;
}
Remarque: je vous conseillerais en fait de ne pas les utiliser car ils fonctionnent mal avec C ++ (les destructeurs d'objets locaux ne seraient pas appelés) et il est vraiment difficile de comprendre ce qui se passe. Renvoyez plutôt une sorte d'erreur.
if()
. Je n'y vois pas de danger; quelqu'un d'autre peut-il ici?
L'ancien C ordinaire ne prend pas en charge les exceptions de manière native.
Vous pouvez utiliser d'autres stratégies de gestion des erreurs, telles que:
FALSE
et utiliser une last_error
variable ou une fonction.Voir http://en.wikibooks.org/wiki/C_Programming/Error_handling .
GetLastError()
dans l'API Windows.
Il n'y a pas de mécanisme d'exception intégré en C; vous devez simuler les exceptions et leur sémantique. Ceci est généralement réalisé en s'appuyant sur setjmp
et longjmp
.
Il y a pas mal de bibliothèques autour, et j'en implémente encore une autre. Cela s'appelle exceptions4c ; c'est portable et gratuit. Vous pouvez l'examiner et le comparer à d' autres alternatives pour voir celle qui vous convient le mieux.
C est capable de lancer une exception C ++, ce sont de toute façon des codes machine. Par exemple, dans 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
dans 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;
}
pour le compiler
gcc -o bar.o -c bar.c && g++ a.cc bar.o && ./a.out
production
good 1976
http://mentorembedded.github.io/cxx-abi/abi-eh.html a plus d'informations sur__cxa_throw
.
Je ne sais pas s'il est portable ou non, et je le teste avec 'gcc-4.8.2' sous Linux.
_ZTII
signifie typeinfo for long
, par exemple echo '_ZTIl' | c++filt
. C'est le schéma de mutilation g ++.
Cette question est très ancienne, mais je suis juste tombée dessus et j'ai pensé partager une technique: diviser par zéro ou déréférencer un pointeur nul.
La question est simplement «comment lancer», pas comment attraper, ni même comment lancer un type spécifique d'exception. J'ai eu une situation il y a longtemps où nous devions déclencher une exception de C pour être interceptée dans C ++. Plus précisément, nous avons eu des rapports occasionnels d'erreurs d '"appel de fonction virtuelle pure", et avons dû convaincre la fonction _purecall du runtime C de lancer quelque chose. Nous avons donc ajouté notre propre fonction _purecall qui divisée par zéro et boom, nous avons obtenu une exception que nous pourrions attraper sur C ++, et même utiliser une pile amusante pour voir où les choses ont mal tourné.
Sur Win avec MSVC, il y a __try ... __except ...
mais c'est vraiment horrible et vous ne voulez pas l'utiliser si vous pouvez l'éviter. Mieux vaut dire qu'il n'y a pas d'exceptions.
C n'a pas d'exceptions.
Il existe diverses implémentations hacky qui tentent de le faire (un exemple sur: http://adomas.org/excc/ ).
Comme mentionné dans de nombreux threads, la manière "standard" de faire cela est d'utiliser setjmp / longjmp. J'ai posté une autre solution de ce type sur https://github.com/psevon/exceptions-and-raii-in-c C'est à ma connaissance la seule solution qui repose sur le nettoyage automatique des ressources allouées. Il implémente des pointeurs intelligents uniques et partagés, et permet aux fonctions intermédiaires de laisser passer les exceptions sans intercepter tout en ayant leurs ressources allouées localement correctement nettoyées.
C ne prend pas en charge les exceptions. Vous pouvez essayer de compiler votre code C en C ++ avec Visual Studio ou G ++ et voir s'il se compilera tel quel. La plupart des applications C se compileront en C ++ sans modifications majeures, et vous pouvez ensuite utiliser la syntaxe try ... catch.
Si vous écrivez du code avec le modèle de conception Happy path (c'est-à-dire pour un périphérique intégré), vous pouvez simuler le traitement des erreurs d'exception (alias deffering ou enfin émulation) avec l'opérateur "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;
}
Il ne fait pas réellement de gestionnaire d'exceptions, mais il vous permet de gérer les erreurs à la sortie de la fonction.
PS Vous devez faire attention à n'utiliser goto qu'à partir de portées identiques ou plus profondes et ne jamais sauter de déclaration de variable.