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 :

Gestions d'erreurs en c++


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut Gestions d'erreurs en c++
    Bonjour à tous. Étant arrivé à un stade de mon projet (une GUI) ou je dois décider d'une politique de gestion d'erreurs, j'aimerais votre avis. Ce projet utilise la SFML (qui ne lance aucune exception) et la STL (qui lance beaucoup d'exception). Ce projet est une librairie, la question ne concerne donc pas "les exceptions dans mon projet" mais "les exceptions pour les utilisateurs du projet".

    Les questions :

    -Quel impact à la gestion des exceptions sur les performances ?
    -Peut-on se débrouiller pour que la STL ne lance jamais d'exception (comme pour la version de new qui renvoie en pointeur NULL en cas d'échec) ?
    -Que faire dans les constructeurs si je décide de ne pas utiliser les exceptions ?
    -Utiliser des exceptions alors que la SFML n'en utilise pas, est-ce vraiment gênant ?
    -Dans le cas ou je n'utilise pas d'exceptions, où mettre les messages d'erreurs ?
    -Dans le cas où j'utilise les exceptions, est-ce un avantage de utiliser les classes d'exceptions de la STL ?
    -Que me conseiller vous (politique de gestion d'erreurs à la C ou avec exception)?

    Merci à tous.

  2. #2
    Nouveau candidat au Club
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 3
    Par défaut
    Bonjour.
    j'ai pas le temps de te répondre dans les détails, mais si tu enlève complétement les exceptions (option de compilation dans Visual C++) tu gagne en performances, sur un exécutable de 0,5Mo j'avais gagné 4% de vitesse, et 15% de taille de l'exécutable, mais ce n'est pas tout le temps pareil.
    Si tu désactive la gestion des exceptions dans ton programme tu risque d'avoir quelques problèmes pour gérer les erreurs provenant de la STL.

    dans ton code source tu peut faire quasiment sans les exceptions, par exemple la valeur de retour des fonction renvoie le code d'erreur si il y en a une. et tu fais tout les vérifications avec des conditions, c'est plus rapide niveau performances processeur, mais ton code sera peut être plus compliqué à lire. Comme en C quoi..

    Si tu développe proprement tu devrais pouvoir t'en passer à la limite mais c'est un peu risqué.

  3. #3
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut
    dans ton code source tu peut faire quasiment sans les exceptions, par exemple la valeur de retour des fonction renvoie le code d'erreur si il y en a une. et tu fais tout les vérifications avec des conditions, c'est plus rapide niveau performances processeur, mais ton code sera peut être plus compliqué à lire. Comme en C quoi..
    Oui, pas de problème la dessus, c'était plutôt comment demander à la STL de générer une valeur de retour au lieu d'une exception (surtout que dans les constructeurs...).

    j'ai pas le temps de te répondre dans les détails, mais si tu enlève complétement les exceptions (option de compilation dans Visual C++) tu gagne en performances, sur un exécutable de 0,5Mo j'avais gagné 4% de vitesse, et 15% de taille de l'exécutable, mais ce n'est pas tout le temps pareil.
    Ok merci, j'espère que gcc propose la même option...

  4. #4
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,
    Citation Envoyé par NoIdea Voir le message
    Bonjour à tous. Étant arrivé à un stade de mon projet (une GUI) ou je dois décider d'une politique de gestion d'erreurs, j'aimerais votre avis. Ce projet utilise la SFML (qui ne lance aucune exception) et la STL (qui lance beaucoup d'exception). Ce projet est une librairie, la question ne concerne donc pas "les exceptions dans mon projet" mais "les exceptions pour les utilisateurs du projet".

    Les questions :

    -Quel impact à la gestion des exceptions sur les performances ?
    Normalement, il y a très peux de différence en terme de performance.

    Les exceptions sont, généralement, gérées sur le modèle SJLJ (Set Jump, Long Jump). L'idée générale étant de remonter la pile d'appel jusqu'à ce que l'on se trouve en position de gérer l'exception

    Si tu place un code de récupération de l'exception et qu'elle n'est jamais lancée, tu obtiens simplement une partie de code qui ne sera pas exécutée
    -Peut-on se débrouiller pour que la STL ne lance jamais d'exception (comme pour la version de new qui renvoie en pointeur NULL en cas d'échec) ?
    Certaines implémentations le permettent, avec les options de compilation "qui vont bien"... Mais pas toutes
    -Que faire dans les constructeurs si je décide de ne pas utiliser les exceptions ?
    créer ton propre allocateur ?

    Ce n'est, normalement, pas tant un problème au niveau du constructeur (qui, rappelons le, est la seule fonction ne renvoyant rien), qu'un problème au niveau de new / new[]...

    Tu peux parfaitement envisager de surcharger cet opérateur (ces opérateurs) de manière à ce qu'ils renvoient NULL si une exception a été lancée

    Mais bon, cela impliquera malgré tout que tu devra vérifier chaque fois que l'allocation a réussi (en vérifiant que le pointeur renvoyé par new ne soit pas nul).
    -Utiliser des exceptions alors que la SFML n'en utilise pas, est-ce vraiment gênant ?
    Pas outre mesure.

    Si une exception est lancée par une fonction qui est appelée par SFML, elle remontra la pile d'appel jusqu'à sortir de SFML. Tu pourra toujours la récupérer à ce moment là
    -Dans le cas ou je n'utilise pas d'exceptions, où mettre les messages d'erreurs ?
    La seule solution sera sans doute une variable globale, ou assimilée, avec tous les problèmes que cela peut impliquer
    -Dans le cas où j'utilise les exceptions, est-ce un avantage de utiliser les classes d'exceptions de la STL ?
    Cela peut en être un dans le sens où tu peux alors faire dériver tes exceptions personnalisées des exceptions de la SL.

    Si tu veux simplement récupérer l'exception "de base", tu peux alors faire un catch(std :: excepion &e ) qui les récupérera d'office toutes
    -Que me conseiller vous (politique de gestion d'erreurs à la C ou avec exception)?
    Les exceptions permettent généralement l'obtention d'un code plus simple.

    Il est très (trop ) facile de ne pas prendre en compte le retour de fonction, ou d'oublier un code d'erreur précis, et toute ta logique peut en souffrir.

    Avec la gestion d'exception, tu n'a quasiment plus à t'inquiéter de cela: elle remontera la pile d'appel, et il n'y a que quand tu sais être en mesure d'apporter une (partie de la) solution que tu dois t'inquiéter de savoir si une exception a été lancée ou non

    Ceci dit, il y a parfois quelques cas dans lesquels le retour d'erreur est une solution malgré tout acceptable, et il n'est même pas exclu d'envisager de mélanger les deux
    Merci à tous.
    De rien
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut
    Cette réponse, très complète amène d'autres questions :

    -Quand une exception doit-elle être lancée ?
    -----Quand le programme segfaultera si elle n'est pas traitée ?
    -----Si il s'agit d'un problème inhabituel même si il n'y aura pas de problème majeur (le chargement d'une image à échoué => image valide mais blanche).
    -Faut-il vérifié la validité des arguments passés en paramètre (si la fonction spécifie : "il ne faut pas passer NULL", faut-il faire un if(NULL) throw ?)

    Cela peut en être un dans le sens où tu peux alors faire dériver tes exceptions personnalisées des exceptions de la SL.

    Si tu veux simplement récupérer l'exception "de base", tu peux alors faire un catch(std :: excepion &e ) qui les récupérera d'office toutes
    Cette réponse me parait un peu ambiguë car je parle des utilisateurs : préfèreront-ils n'avoir a traiter que le type d'exception de base de la STL ou préfèreront-ils que je crée mon propre type ?

    Ceci dit, il y a parfois quelques cas dans lesquels le retour d'erreur est une solution malgré tout acceptable, et il n'est même pas exclu d'envisager de mélanger les deux
    Dans ce cas, dans quel cas utiliser l'un, dans quel cas utiliser l'autre ?

  6. #6
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par NoIdea Voir le message
    Cette réponse, très complète amène d'autres questions :

    -Quand une exception doit-elle être lancée ?
    -----Quand le programme segfaultera si elle n'est pas traitée ?
    -----Si il s'agit d'un problème inhabituel même si il n'y aura pas de problème majeur (le chargement d'une image à échoué => image valide mais blanche).
    Deux écoles s'affrontent sur ce terrain:

    La première estime qu'une exception ne doit être lancée que lors de la survenue d'un événement... exceptionnel.

    L'autre estime que c'est une manière assez facile de faire remonter les erreurs jusqu'au point où il sera possible d'y apporter une solution.
    -Faut-il vérifié la validité des arguments passés en paramètre (si la fonction spécifie : "il ne faut pas passer NULL", faut-il faire un if(NULL) throw ?)
    Une exception est, au minimum, lancée lorsque tu constate que le système est dans un état incohérent, ou que la suite des opérations risque de placer le système dans un état incohérent.

    Si tu as une fonction qui doit renvoyer une référence basée sur un pointeur qui peut être nul, par exemple, tu ne peux décemment pas envisager de renvoyer une référence sur quelque chose... d'inexistant.

    Mais, comme tu n'as aucune possibilité de signaler que la référence est invalide, tu n'aura sans doute pas d'autre choix que de... lancer une exception.

    Pour ce qui est du passage d'un pointeur en argument, j'utiliserais peut être plutôt une assertion, mais, si tu estimes effectivement que le fait de passer un pointeur nul placera le système dans un état incohérent (comprenons nous: ca peut ne placer qu'un objet dans un état incohérent ) tu peux parfaitement envisager de lancer une exception.

    Cependant, il faut avouer que, idéalement, tu devrais surtout faire en sorte que la logique suivie lors du passage du pointeur comme argument s'assure de ne pas passer de pointeur nul
    Cette réponse me parait un peu ambiguë car je parle des utilisateurs : préfèreront-ils n'avoir a traiter que le type d'exception de base de la STL ou préfèreront-ils que je crée mon propre type ?
    A la limite, tu t'en fous...

    Si tu fais dériver certaines de tes exceptions de std::runtime_error, d'autres de std::logical_error et d'autres encore de std::invalid_argument, la manière dont l'utilisateur les utilisera n'aura strictement aucune importance de ton coté:

    S'il décide de les gérer sur base de catch (std::exception & e), il aura peut être du mal à déterminer ce qui a pu réellement se passer, et, s'il décide de les gérer sur base de catch(MySpecialException &e), il sera effectivement en mesure d'apporter une solution cohérente au problème qui est survenu.

    Quoi qu'il en soit, ce n'est pas de ton ressort, même si tu peux effectivement essayer de l'orienter vers une solution ou une autre en fonction de la situation
    Dans ce cas, dans quel cas utiliser l'un, dans quel cas utiliser l'autre ?
    Il est très difficile de donner une règle générale à cette question.

    On pourrait cependant dire que le retour d'erreur peut être utiliser quand tu sais que tu dispose directement de la possibilité d'apporter la solution au problème s'il survient.

    Si tu dois attendre de retourner dans la fonction qui a appelé la fonction qui a appelé la fonction dans laquelle le problème survient, les exceptions seront clairement plus efficaces et faciles à utiliser.

    Il y a eu ici un débat sur le sujet il y a déjà quelques temps... Peut être devrais tu faire la recherche du sujet
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #7
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut
    La première estime qu'une exception ne doit être lancée que lors de la survenue d'un événement... exceptionnel.

    L'autre estime que c'est une manière assez facile de faire remonter les erreurs jusqu'au point où il sera possible d'y apporter une solution.
    Ce n'est pas exactement les 2 cas que j'ai cités, mais je suppose qu'on peut les considérés comme équivalent.

    Pour ce qui est du passage d'un pointeur en argument, j'utiliserais peut être plutôt une assertion, mais, si tu estimes effectivement que le fait de passer un pointeur nul placera le système dans un état incohérent (comprenons nous: ca peut ne placer qu'un objet dans un état incohérent ) tu peux parfaitement envisager de lancer une exception.
    Ce que je voulais dire concernait plutôt : "Dois-je considérer que l'utilisateur de la fonction respecte la documentation et donc ne pas faire de vérification de validité des arguments" ou "Ma fonction doit-elle vérifié que les arguments sont valides".

    Il y a eu ici un débat sur le sujet il y a déjà quelques temps... Peut être devrais tu faire la recherche du sujet
    J'avais fait une recherche en tapant "les exceptions" dans la recherche sur ce forum, j'ai regardé la première et une partie de la deuxième page sans résultat.

  8. #8
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par NoIdea Voir le message
    Ce que je voulais dire concernait plutôt : "Dois-je considérer que l'utilisateur de la fonction respecte la documentation et donc ne pas faire de vérification de validité des arguments" ou "Ma fonction doit-elle vérifié que les arguments sont valides".
    Je vais encore devoir faire une réponse de normand à cette question :aile:...

    Il est prudent de se dire que, s'il y a une bêtise à faire, tu trouvera fatalement un utilisateur qui la fera.

    Ce n'est, ni plus ni moins , qu'une mise en application de la loi Murphy

    De plus, il faut de toutes manières toujours te poser la question de ce qui peut se passer si l'utilisateur "joue à l'imbécile", l'idéal étant toujours de repérer ce genre de cas le plus tôt possible.

    Maintenant, il y a malgré tout des cas où tu peux effectivement "zapper" la vérification.

    Tu dois donc, pour chaque situation, évaluer le risque d'obtenir un argument incohérent et les conséquences qu'il pourra impliquer.

    J'avais fait une recherche en tapant "les exceptions" dans la recherche sur ce forum, j'ai regardé la première et une partie de la deuxième page sans résultat.
    Je crois que le titre du débat était de l'ordre "retour d'erreur ou exception", mais sans certitude

    Il faut dire qu'en ayant participé à plus de 3000 discussions différentes, j'ai un peu de mal à en trouver une en particulier, surtout qu'elle n'est pas vraiment récente
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  9. #9
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par NoIdea Voir le message
    Ce que je voulais dire concernait plutôt : "Dois-je considérer que l'utilisateur de la fonction respecte la documentation et donc ne pas faire de vérification de validité des arguments" ou "Ma fonction doit-elle vérifié que les arguments sont valides".
    Pareil que Flob. Si ton utilisateur ne respecte pas le contrat de ta fonction, ta fonction n'est pas tenue de respecter sa part du contrat non plus. Donc les tests de cohérences sont inutiles car celles ci font parties du contrat de ta classe. (cf Programmation par contrat, application en C++ par Julien Blanc).

  10. #10
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Citation Envoyé par NoIdea Voir le message
    -----Si il s'agit d'un problème inhabituel même si il n'y aura pas de problème majeur (le chargement d'une image à échoué => image valide mais blanche).
    -Faut-il vérifié la validité des arguments passés en paramètre (si la fonction spécifie : "il ne faut pas passer NULL", faut-il faire un if(NULL) throw ?)
    Personnelement je ferais comme pour la S(T)L, le non respect des pré-requis implique un comportement indéfini, sauf si tu juges utile de lancer une exception (je dirai pour les pré-requis qui peuvent être difficiles à vérifier).

    Je n'ai pas de lien vers la conversation dont parle koala, mais il était notamment question des bibliothèque microsoft qui préfère l'utilisation de retour pour les erreures. (il me semble)

    Personnelement, ce que j'avais retenue d'interresent était la proposition d'utilisation simultané des deux méthodes, les exceptions dès que la fonction viole ses invariants et le retour pour le reste (en gros), ca me semble une bonne solution.

    Une solution radicale si tu veus t'assurer que ta bibliothèque ne lancera pas d'exception est de toutes les "avaler", pour faire simple toutes tes fonctions contiennent un bloc try catch de la forme try{} catch(...){/*traitment générique*/} (et d'autre catch avant pour traiter des exceptions spécifiques), ainsi aucune exception ne peut être émise par ta bibliothèque. Je trouve ca assez sale mais ca doit marcher. (c'est une des technique possible pour s'assurer qu'un destructeur ne lance pas d'exception par exemple).

Discussions similaires

  1. gestion d'erreur et de transactions....
    Par Dge dans le forum MS SQL Server
    Réponses: 9
    Dernier message: 08/02/2006, 22h20
  2. [Struts-Validator] Gestion d'erreurs
    Par sylvain_neus dans le forum Struts 1
    Réponses: 14
    Dernier message: 09/04/2004, 15h15
  3. [XSLT]Est ce qu'il y'a la gestion des erreur en xslt ?
    Par miloud dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 04/02/2004, 17h19
  4. [LG]tests pour la gestion d'erreur
    Par le 27 dans le forum Langage
    Réponses: 3
    Dernier message: 22/12/2003, 20h44
  5. [LG]gestion des erreurs
    Par frontin dans le forum Langage
    Réponses: 3
    Dernier message: 29/11/2003, 22h41

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