2009-09-21 5 views
3

Quelles techniques puis-je utiliser pour éviter les exceptions en C++, comme mentionné dans Google's style guide?Comment puis-je éviter d'utiliser des exceptions en C++?

+4

Pourriez-vous préciser votre question? En l'état, la réponse semble être: vous ne lancez pas d'exceptions et essayez d'éviter les circonstances qui poussent le code externe à lancer des exceptions par un codage défensif. –

+0

oui votre compréhension est correcte.Qu'est-ce que le codage défensif? – yesraaj

+2

Notez que, même compte tenu de ce Dentranchante dit (http://stackoverflow.com/users/57428/sharptooth) - et avec tout le respect dû aux gens intelligents à Google -, je considère cela comme un guide de style stupide. Comme il est pratiquement impossible d'éviter les exceptions en C++, vous devrez probablement écrire du code de sécurité. Faire cela sans utiliser d'exceptions signifie que vous devez faire face à tous les inconvénients des exceptions, mais renoncer à leurs avantages. Maintenant, à quoi ça sert? – sbi

Répondre

8
  1. ne jetez pas des exceptions.
  2. ne pas utiliser STL (qui repose en grande partie sur les exceptions).
  3. Utilisez uniquement new(std::nothrow) ou remplacer ::operator new pour retourner 0 en cas d'échec

Notez qu'en évitant les exceptions, vous jetez efficacement beaucoup de bibliothèques utiles, y compris Boost. Fondamentalement, vous devrez tout programmer à partir de zéro.

+0

Je ne savais pas du TSL « reposait largement sur des exceptions », et bien je me souviens que STL incompatible avec les exceptions utilisées pour être un gros problème. Mais je suppose que c'est le cas au moins dans la mesure où il n'a pas d'autre moyen de gérer les échecs d'allocation. –

+1

Ce n'est pas seulement une question d'échec d'allocation. Les exceptions sont le seul moyen d'indiquer l'échec des constructeurs, notamment des constructeurs de copie appelés sur les éléments lors des insertions. – avakar

+1

Découvrez le EASTL, un STL sans exception. –

1

Le guide de style dit qu'ils "n'utilisent pas d'exceptions" ce qui est juste - ils ne les lancent pas et n'appellent rien qui puisse les lancer (par exemple, ils utilisent le new(std::nothrow) au lieu de new d'habitude parce que ce dernier jetteront bad_alloc quand il ne parvient pas à allouer de la mémoire.

+1

Comment parviennent-ils à utiliser les librairies qui génèrent des exceptions? – yesraaj

+0

Ou ils n'utilisent pas ces bibliothèques –

+0

Ils peuvent les envelopper et avoir et une prise (...) autour de tout le contenu dans toutes les fonctions d'emballage. – Laserallan

0

Dans certains compilateurs, vous pouvez peut-être désactiver la gestion des exceptions. Cela pourrait provoquer des résultats inattendus avec du code externe cependant - ce n'est pas quelque chose que je voudrais essayer. À part cela, la première étape évidente serait d'éviter de lancer des exceptions à partir de votre propre code, probablement avec une utilisation généreuse du nothrow directive, et d'essayer d'éviter de lancer des exceptions du code externe (tiers) par defensive programming. Cela signifie que votre code doit toujours être conscient des éventuelles conditions de défaillance exceptionnelles externes, telles que l'insuffisance de mémoire, l'espace disque disponible, la perte d'une connexion Internet, une défaillance matérielle et un nombre d'autres circonstances. cela pourrait provoquer le lancement du code ...

Dans certains cas, vous pouvez utiliser des versions exemptes d'exceptions de certains codes (par exemple, lancement d'un nouveau jeu ou nouveau lancement).

3

Ne pas lancer d'exceptions dans votre propre code est relativement facile: vous n'utilisez simplement pas l'instruction throw.

ne pas jeter des exceptions des échecs d'allocation de mémoire est un peu plus douloureux: soit vous n'utilisez pas normale new (utiliser new(std::nothrow) ou malloc ou quelque chose à la place), ou si vous utilisez une option de compilateur non standard pour l'obtenir pour faire quelque chose non standard quand il échoue (par exemple, terminez immédiatement votre programme, ou renvoyez 0), ou vous substituez operator new pour faire quelque chose de non standard en cas d'échec.

Si votre approche choisie est de terminer immédiatement le programme, vous pouvez l'implémenter avec set_new_handler(), que j'avais oublié jusqu'à ce que litb me le rappelle. Cela laisse le problème de gérer les exceptions générées par les bibliothèques C++ que vous ne gérez pas. En général, vous devrez envelopper les appels de bibliothèque dans un emballage qui ressemble à ceci:

int DoSomething(int &output, const int input) throw() { 
    try { 
    output = library_do_something(input); 
    return 1; 
    } catch (...) { 
    return 0; 
    } 
} 

Les catch (...) prises tous les possibles C++ exceptions library_do_something (ainsi que l'opérateur d'affectation sur output, ce qui est pertinent ici), jette toutes les informations qu'ils peuvent contenir, puis mappe tous ces échecs à 0.

Notez que ce style signifie que vous ne pouvez pas utiliser RAII du tout, pas même un peu, parce que vous avez aucun moyen de défaillance de signalisation au sein d'un constructeur. Tout le point de RAII est que vous acquérez toutes vos ressources à l'intérieur des constructeurs afin qu'ils soient correctement libérés par un destructeur lors de la propagation des exceptions. Mais l'acquisition de ressources est quelque chose qui peut toujours échouer. Donc, vous ne pouvez pas le faire à l'intérieur d'un constructeur.

+0

Vous pouvez installer un nouveau gestionnaire. L'opérateur new l'appellera lorsqu'il n'aura pas de mémoire disponible, et à partir de ce gestionnaire, vous pourrez soit obtenir de la mémoire, soit terminer le programme. –

+0

J'avais oublié 'set_new_handler()', merci, litb! Je suis en train de mettre à jour ma réponse. –

+0

Faites simplement 'kill (0,9)' au lieu de lancer une exception. OK, vous allez aussi embrasser tout votre groupe de process au revoir, mais cette exception embêtante ne dérangera pas votre beau code! ;-) –

2

Je suis intéressé de savoir pourquoi on voudrait éviter des exceptions en C++ et quel mécanisme on pourrait les remplacer par faire face à la réalité de l'échec inattendu tout en conservant la structure décente. Bien sûr, les ajouter à une base de code existante qui n'utilise pas la sémantique de type RAII est extrêmement coûteux - mais si l'on fait du développement de champs verts, quelle alternative suggéreriez-vous et comment justifier de ne pas utiliser des bibliothèques de haute qualité? utiliser des exceptions par rapport à l'écriture de vos propres alternatives d'exception/sans bug?

+0

En plus des problèmes de performance et d'espace des exceptions, qui existent empiriquement même si les gens les nient, certaines plateformes ne supportent tout simplement pas les exceptions de manière fiable. Par exemple, les compilateurs C++ de certaines machines embarquées n'ont tout simplement pas d'exception de travail. – Crashworks

+2

Personnellement, je n'aime pas utiliser des exceptions en C++, car il rend extrêmement difficile de prédire le flux de contrôle du programme. Puisque n'importe quelle fonction C++ peut lancer n'importe quelle exception sans la déclarer, l'utilisation d'exceptions signifie que vous ne pouvez pas prédire ce que la fonction * any * fera à moins que vous ne rampiez sur l'arbre d'appel * entier * en dessous. Cela signifie que la vérification du comportement d'une fonction par rapport aux exceptions est un problème avec l'augmentation géométrique des coûts pour le programmeur. Java, OTOH, fait les choses correctement - les méthodes Java déclarent les exceptions qu'elles peuvent lancer, et les déclarations sont appliquées au moment de la compilation. –

+0

@JeremyFriesner: C'est la raison pour laquelle nous codons toujours les garanties de sécurité exceptionnelles - de sorte que le chemin d'exécution n'a pas d'importance. – Tom

Questions connexes