IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

bloc try catch dans le main, est-ce le diable?


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 290
    Billets dans le blog
    2
    Par défaut bloc try catch dans le main, est-ce le diable?
    Bonjour tout le monde,

    je suis en train de me remettre au c++ après un gros détour vers d'autres langages plus... lents, on va dire

    Et là je tombe sur une question existentielle. Je vous explique:
    Je fais un petit programme. Il va comporter 3 classes de taille moyenne, ainsi que quelques petites fonctions et structures utilitaires. Ce programme est un "one shot": on le lance dans une console cmd, il fait des trucs, il génère son résultat, puis il se ferme.

    Les trois classes en question accèdent à des ressources fortement susceptibles de générer des exceptions lors de leur accès. Heureusement pour moi, je peux me permettre d'accéder à ces ressources une fois, récupérer ce dont j'ai besoin, puis libérer cette ressource. Ces ressources sont des fichiers, de la base de donnée, et quelques appels à des web services.

    Donc, j'ai opté pour du RAII: pour chacune de ces 3 classes, c'est lors de l'appel au constructeur que je récupère les données dont j'ai besoin. Et c'est là que j'ai un gros doute, car du coup, mon main() ressemble à ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    int main(int argc, char** argv)
    {
    	//... gestion des paramètres d'entrée
     
    	try
    	{
    		GIS_Reader reader( argv[1] );
    		GIS_XemManager xem_manager( argv[2] );
    		GIS_Computer computer( reader, xem_manager );
     
    		computer.Compute();
    	}
    	catch( exception & ex )
    	{
    		// message d'erreur
    	}
    }
    Ce qui me turlupine, c'est ce groc bloc try/catch dans le main. Depuis toujours, il me semblait que ce genre de pratique c'était très mal, mais aujourd'hui je suis incapable de dire pourquoi. Et cette façon de faire me convient particulièrement, au moins dans ce cas là: un petit programme qu'on lance une fois, dont l'exécution est rapide (quelques secondes normalement), et que si ça marche pas, on veut juste savoir pourquoi et relancer la commande.

    Donc voilà, c'était juste pour savoir si vous savez pourquoi ce type de pratique est déconseillée, et si dans mon cas ça peut vraiment poser des problèmes.


    Cordialement.
    r0d.

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Par défaut
    Hello

    Je pense que c'est vu comme une mauvaise technique dans le sens où c'est la technique du paresseux. L'interception d'exception doit pouvoir permettre la reprise sur erreur (si elle est possible), et cette reprise se fait bien rarement dans le main. Il faut aussi faire gaffe à libérer les éventuelles ressources consommées par l'objet avant le lancement de l'exception, mais je pense que ce cas ne te concerne pas.

    Donc dans ton cas, ça ne me choque pas du tout. A ta place, je ne m'emmerderai pas et je continuerai comme ça.

  3. #3
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    S'il n'y a qu'un try/catch dans le main, je dirais qu'on a opté pour la version pauvre de la gestion d'erreurs : On affiche un message "désolé" avant de planter. Ce qui peut être suffisant dans certains contextes (utilitaire en ligne de commande).

    Par contre, ne pas avoir de try/catch dans le main me semblerait suspect : On ne fourni même pas ce service minimal, en dernier recours.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  4. #4
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Je ne trouve pas cela spécialement choquant. En fait, pas mal de frameworks utilisent ce genre de fonction main() englobée dans un try... catch (parfois plusieurs, même).

    J'y vois deux intérêts
    1- cela permet d'intercepter d'éventuelles exceptions non gérées. Normalement, il ne devrait pas y en avoir, mais un programme fonctionne rarement normalement, surtout au début. Ces erreurs imprévisibles sont souvent les plus difficiles à débuguer. La clause catch peut aider à les corriger, en remontant des informations sur l'état du programme juste avant sa sortie.

    2- cela permet, en cas de gros problème, de prendre d'éventuelles mesures conservatoires, sauvegarde de données, fermeture de ports, écriture de logs

    Mais comme d'autres l'ont dit, cela ne te dispense pas de gérer les exceptions dans le reste du programme. C'est une sorte de dernier recours.

    Francois

  5. #5
    Membre Expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    S'il n'y a qu'un try/catch dans le main, je dirais qu'on a opté pour la version pauvre de la gestion d'erreurs : On affiche un message "désolé" avant de planter. Ce qui peut être suffisant dans certains contextes (utilitaire en ligne de commande).

    Par contre, ne pas avoir de try/catch dans le main me semblerait suspect : On ne fourni même pas ce service minimal, en dernier recours.
    De même, j'ai pas mal étudié la question pour un jeu où j'ai du mettre en place toute une stratégie pour recouvrer de certaines érreurs et passser dans cerains processus pour les autres (comme m'envoyer un mail avec le log, etc.) mais j'en arrive toujours au même point où si je veux être sur d'avoir fait le maximum pour avoir les infos sur ce qu'il s'est passé, le minimum syndical est d'avoir ce dernier try/catch dans le main pour une tentative désespérée de log.

  6. #6
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 290
    Billets dans le blog
    2
    Par défaut
    Merci pour vos interventions.
    Mais j'avoue que j'ai encore du mal à comprendre ce qui se passe "en dessous du capot" avec les exceptions.

    Par exemple, est-ce que ça a un coût en terme de performance ce try/catch dans le main? Puisque finalement, l'intégralité du code est inclu dedans.

    Autre question (je reviens aux bases, j'espère que vous ne m'en tiendrez pas rigueur, mais je pense que ce n'est pas mauvais de le faire de temps en temps): en testant un peu mon programme dans le but de prévoir un peu les différent types d'erreurs à gérer, j'ai généré un dépassement d'index sur un vector. Et en fait, ce dépassement d'index (je ne suis pas sûr que ce soit le bon terme) génère une exception qui n'est pas récupérée par mon catch. Comment se fait-ce?

    Je comprend d'autant moins ce qu'il se passe car si j'utilise vector::at(index) à la place de l'opérateur[], je racupère bien mon "out of range" exception.

    note: je travaille en x64/release.

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Citation Envoyé par r0d Voir le message
    Et en fait, ce dépassement d'index (je ne suis pas sûr que ce soit le bon terme) génère une exception qui n'est pas récupérée par mon catch. Comment se fait-ce?

    Je comprend d'autant moins ce qu'il se passe car si j'utilise vector::at(index) à la place de l'opérateur[], je racupère bien mon "out of range" exception.
    C'est normal.
    La méthode at() lance une exception, mais pas l'opérateur [].

    Voir CPlusPlus.com au sujet de la méthode at() :

    The difference between this member function and member operator function operator[] is that vector::at signals if the requested position is out of range by throwing an out_of_range exception.

    Il faut choisir entre sécurité et rapidité.

  8. #8
    Membre Expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Par défaut
    Citation Envoyé par r0d Voir le message
    Merci pour vos interventions.
    Mais j'avoue que j'ai encore du mal à comprendre ce qui se passe "en dessous du capot" avec les exceptions.

    Par exemple, est-ce que ça a un coût en terme de performance ce try/catch dans le main? Puisque finalement, l'intégralité du code est inclu dedans.
    Il y a un cout :

    - en taille de binaire, parcequ'il faut bien que le code qui remonte l'exception soit inclus dans le binaire;
    - en rapidité d'exécution, mais c'est négligeable tant qu'une exception n'est pas levée, et si elle l'est alors de toutes manières c'est exceptionel. Autrement dit, a ne pas utiliser pour faire de la logique d'application, sinon il y aura au moins les perfs qui seront désastreuses.

    Il me semble que quelqu'un ici avait, lors d'une grosse discussion sur les exception, fait la comparaison avec ou sans exceptions et avait bien du admettre qu'il y a quand même un cout à l'execution "normale". Cela étant dit, faut de sacrées bonnes raisons pour ne pas vouloir payer le prix, comme par exemple bosser sur certains hardwares (voir ma réponse à cette question : http://programmers.stackexchange.com.../113481#113481 )

  9. #9
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par r0d Voir le message
    Par exemple, est-ce que ça a un coût en terme de performance ce try/catch dans le main? Puisque finalement, l'intégralité du code est inclu dedans.
    En fait, pas tout à fait... Ce que ta boucle try/catch dans le main dit, c'est que si l'une des trois fonctions que tu y appelles renvoie une exception, il faut la traiter, pas que chaque ligne de ton code renvoie des exceptions.

    En fait, les exceptions ne se produisent que quand on leur dit de le faire (throw). Elle remontent alors dans la hierarchie d'appels de ton programme, jusqu'à rencontrer un catch, éventuellement jusqu'à ton main().

    Ce qui a un cout en terme de performance, ce n'est pas la gestion de l'exception (la boucle try/catch) mais le controle qui déclenche, au niveau le plus bas, l'exception. Pour un vecteur, tester le dépassement à chaque accès est affreusement couteux, c'est pour cela que [] ne le fait pas. Si tu en as besoin at() le fait...

    Francois

Discussions similaires

  1. Réponses: 10
    Dernier message: 06/10/2010, 17h06
  2. Visibilité de mon tableau dans bloc try catch
    Par erox44 dans le forum Collection et Stream
    Réponses: 1
    Dernier message: 18/05/2010, 15h13
  3. Faire un return dans un bloc try catch
    Par alizee971 dans le forum Débuter avec Java
    Réponses: 2
    Dernier message: 13/08/2008, 19h38
  4. Problème try-catch dans mon code
    Par little pepito dans le forum Langage
    Réponses: 7
    Dernier message: 11/06/2007, 12h22
  5. Try catch dans une dll - possible ?
    Par Pendary dans le forum C++Builder
    Réponses: 1
    Dernier message: 02/03/2007, 16h48

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo