Différence entre la gestion des exceptions en C ++ et Java?

En Java, si une ligne de code spécifique provoque le blocage du programme, alors l’exception est interceptée et le programme continue à s’exécuter.

Cependant, en C ++, si j’ai un morceau de code qui provoque le blocage du programme, comme:

try { int x = 6; int *p = NULL; p = reinterpret_cast(x); *p = 10; // the program crashed here cout << "x = " << *p << endl; } catch(const char* Message) { cout << "There is an run-time error"; } 

Ensuite, le programme plante toujours et l’exception n’est pas interceptée.

Alors, quel est le sharepoint la gestion des exceptions en C ++? Est-ce que je comprends mal quelque chose?

La ligne qui plante est en train de déréférencer un pointeur non valide. En C ++, cela ne lève pas d’exception. Au lieu de cela, c’est un comportement indéfini.

Il n’existe pas d’ exception de pointeur nul en C ++ , contrairement à Java qui lève une exception de pointeur nul. Au lieu de cela, supprimer un pointeur invalide entraînera un comportement indéfini. Le comportement indéfini n’implique pas toujours un plantage, mais s’il se bloque, vous avez de la chance.

Aperçu de la langue:

Enfin et RAII

L’une des différences les plus significatives entre C ++ et Java est que Java prend en charge une instruction finally . Le code du bloc finally est toujours exécuté, que le code du bloc catch précédent soit exécuté ou non. Par exemple:

 try { } catch (SomeException e) { } finally { //code here is always exectued. } 

Le but de l’instruction finally est d’autoriser le nettoyage du programmeur à ce stade, par exemple libérer des sockets, fermer des descripteurs de fichiers, etc. Même si Java exécute un ramasse-miettes, la récupération de mémoire ne s’applique qu’à la mémoire et aux autres ressources. Il existe encore des cas où vous devez disposer manuellement des ressources . Maintenant, C ++ n’a pas de déclaration finale, il est donc conseillé aux utilisateurs du langage d’adhérer au principe RAII (l’acquisition de la ressource est une initialisation). Stroustrup a une explication à ce sujet ici: http://www.stroustrup.com/bs_faq2.html# enfin Je préfère l’appeler Resource destruction is deallocation mais lorsque votre object tombe en dehors de la scope, en invoquant le destructeur, ce destructeur doit alors libérer les ressources conservées par l’object.

Par exemple, C ++ 11x fournit un std :: unique_ptr pour gérer ceci:

 void foo() { std::unique_ptr t(new T) try { //code that uses t } catch (...) { } } 

La ressource allouée via new sera supprimée à la fin de la fonction.

attraper toutes les déclarations

Parce que toutes les exceptions en Java héritent d’une classe de base commune Exception si vous souhaitez que votre clause catch attrape une exception, configurez-la comme suit:

 catch (Exception e) { //any exception thrown will land here. } 

En C ++, il n’y a pas de ressortingction sur ce qui peut être jeté ni de classe de base commune pour toutes les exceptions. La pratique standard consiste à former votre classe d’exceptions personnalisée en héritant de std :: exception, mais le langage ne l’impose pas. Au lieu de cela, il existe une syntaxe spéciale pour intercepter toutes les exceptions:

 catch (...) { } 

Exceptions non gérées

C’est un autre domaine où les langues se comportent différemment. En C ++, une exception levée qui n’est pas interceptée appellera std :: terminate. Le comportement par défaut de std :: terminate est d’appeler abort, ce qui génère un SIGABRT et le programme entier s’arrête.

En Java, le comportement consiste à imprimer une trace de stack et à terminer le thread dans lequel s’est produite l’exception non capturée. Cependant, un programmeur Java pouvant fournir un gestionnaire UncaughtException, le comportement peut différer de celui du thread.

Tous les accidents ne sont pas dus à des exceptions non gérées. Pour votre exemple, la norme C ++ indique que le déréférencement du pointeur NULL entraîne un comportement indéfini . Sous Windows, vous pouvez gérer les problèmes qui bloquent votre programme sans déclencher une exception C ++ avec la gestion structurée des exceptions (SEH): __try / __except / __finally . Sous Unix, vous pouvez configurer des gestionnaires de signaux spéciaux.


En outre, il y a une erreur dans votre code. Le gestionnaire d’exceptions pour const char * ne serait appelé que lorsqu’une exception de ce type est levée. Pour les exceptions standard, vous devriez attraper std::exception ou ses sous-classes appropriées. Pour intercepter une exception C ++, utilisez catch (...) .

En fait, vous POUVEZ attraper des exceptions système en C ++. Il existe une option de compilateur (au moins dans Visual Studio) qui vous permet de détecter les exceptions de violation d’access (ce qui explique pourquoi votre programme se bloque).

Java est plus surveillé, ce qui crée une illusion de complexité.

Pensez à ce qui suit:

En Java:

 int x[10]; int i = 20; try { int k = x[i]; } catch (ArrayIndexOutOfBoundsException ex) { //will enter here } 

Int C ++:

 int x[10]; int i = 20; try { if ( i >= 10 ) throw new "Index out of bounds"; int k = x[i]; } catch (...) { //now it will enter here } 

Tout doit être fait pour savoir si vous voulez en laisser plus à l’environnement d’exécution (comme dans le cas de Java) ou si vous voulez vous-même gérer les choses. C ++ vous donne plus de contrôle, mais vous devez faire plus attention.

Votre programme Java se bloquerait également si les exceptions ne étaient pas gérées – pensez-y, si une méthode lève explicitement une exception, vous ne pouvez pas ne pas la gérer, car le compilateur ne vous le permet pas. Si ce n’est pas explicitement, votre programme se bloquera toujours à moins d’être entouré par try / catch.

Si vous demandez pourquoi les exceptions système ne peuvent pas être gérées en C ++, j’ai déjà répondu: elles peuvent le faire, c’est simplement que, par défaut, cette option est désactivée.

Le point d’exception, dans n’importe quelle langue, est ou devrait être de traiter des cas exceptionnels. Mais toujours des cas où vous pouvez faire des hypothèses raisonnables sur l’état global du programme, et éventuellement récupérer. Les erreurs de programmation signifient généralement que vous ne pouvez faire aucune hypothèse sur l’état global du programme et que vous devez terminer le code le plus rapidement possible, en exécutant le moins de code supplémentaire (car vous ne savez pas ce qu’il va faire).

En Java, pratiquement tout est signalé par une exception. Tout, des erreurs courantes attendues (“fichier non trouvé” lors de la tentative d’ouverture d’un fichier) aux erreurs internes critiques (java.lang.VirtualMachineError). C ++ vous donne le choix: si vous détectez une erreur de codage (échec d’assertion), vous pouvez abandonner le processus immédiatement (généralement plus approprié que la publication dans un état inconnu); si “l’erreur” survient normalement (“fichier introuvable”), vous pouvez tester l’état ou utiliser un code de retour (là encore, il est généralement plus approprié qu’une exception). Dans un certain nombre de situations entre les deux (manque de mémoire, par exemple), C ++ utilise des exceptions.

Bien sûr, ce qui est le plus approprié dans une application donnée varie: il existe certainement des cas où “fichier non trouvé” est exceptionnel (par exemple, si le fichier fait partie de l’application et ne peut pas s’exécuter sans elle), et justifie une exception. . De même, dans des cas spécifiques, un pointeur nul peut être utilisé pour contrôler la logique du programme ( if ( ptr == NULL ) ... ) ou correspond à un cas exceptionnel ( if ( ptr == NULL ) throw ... ); dans d’autres cas, un pointeur nul est une erreur de programmation ( assert( ptr != NULL) ).

  1. C ++ et Java ont tous deux des blocs try et catch mais Java a finalement un nouveau bloc qui est toujours exécuté après try et catch.
  2. Java ne jette que des objects mais C ++ jette des données (primitive, pointeur et objects).
  3. C ++ a catch (…) {} pour attraper toutes les exceptions de toutes sortes et Java a catch (Exception e) {} pour intercepter toutes les exceptions.