Partage
  • Partager sur Facebook
  • Partager sur Twitter

Exception et fichier de LOG

    14 février 2020 à 16:06:57

    Bonjour à tous,

    J'essaie d'intégrer un fichier de LOG dans un programme (je développe sous VS avec le module QT VS TOOLS)

    Je viens de "découvrir" les exceptions et je pensais faire de la sorte :

    void toto(int i)
    {
        if (i < 0)
            throw std::runtime_error("la valeur saisie est négative");
    
        // Reste du code
    }
    
    int main()
    {
        
        try 
        {
            toto(-2);
        }
    
        catch (std::exception const& exception)
        {
            emit errorLOG(exception.what());
        }
    
    }



    Premièrement, quel est votre avis sur la façon de faire?

    Et quelle est la différence avec ce code :

    void toto(int i)
    {
        if (i < 0)
            emit errorLOG("la valeur saisie est négative");
        else
        {
            //reste du code
        }
    }
    
    int main()
    {
        toto(-2);
    }



    J'ai un peu du mal à saisir l'intérêt de l'exception.

    Merci pour vos lumières.

    TY

    -
    Edité par ThugYo 14 février 2020 à 16:09:57

    • Partager sur Facebook
    • Partager sur Twitter
      14 février 2020 à 17:59:02

      Attendons les plus calés, mais pour moi si tu utilise try tu peux meme faire des trucs comme des acces hors tableau ça ne plante pas l’appli alors que le deuxieme exemple peux te planter toute l’appli
      • Partager sur Facebook
      • Partager sur Twitter
        14 février 2020 à 19:19:39

        emit n'est pas standard, ça fait quoi?

        Sinon les exceptions, c'est pour dérouter un comportement que l'on sait ne pas pouvoir continuer parce des entrées externes ne sont pas compatibles avec ce que l'on voudrait en faire.

        • Partager sur Facebook
        • Partager sur Twitter
        C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
          14 février 2020 à 19:44:55

          Emit fait partie du framework Qt il emet un signal qui est récupérable par un slot.

          exemple emit fichier téléchargé etc

          • Partager sur Facebook
          • Partager sur Twitter
            17 février 2020 à 10:04:48

            Bonjour,

            Si j'ai bien compris, l'exception, dans le cas où elle est générique, va indiquer qu'il y a eu une erreur. Si je fais un if, je dois savoir quelle erreur je cherche. C'est ça?

            • Partager sur Facebook
            • Partager sur Twitter
              17 février 2020 à 10:32:06

              Un try/catch global, c'est foireux.

              On perd bien trop d'informations importantes.

              L'utilisation d'un whatchdog et la génération automatique d'un dump, c'est bien plus fiable.

              • Partager sur Facebook
              • Partager sur Twitter
              Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                17 février 2020 à 10:35:17

                bacelar a écrit:

                L'utilisation d'un whatchdog et la génération automatique d'un dump, c'est bien plus fiable.


                En français ça donne quoi ? :)

                PS: j'ai pas un gros niveau en dev et j'ai pas le lexique de dev non plus

                • Partager sur Facebook
                • Partager sur Twitter
                  17 février 2020 à 11:56:12

                  Vu la vérification que tu réalises, je te dirai bien de lire les 3 articles sur la programmation par contrat dans mon blog (signature).

                  Un log trace ce qu'il se passe à un moment donné, il n'influe pas (drastiquement) le déroulement flot d'exécution. C'est totalement orthogonal à ce que je résume en dessous. i.e. on peut l'utiliser en plus, ou pas, c'est notre choix.

                  Une exception interrompt le flot d'exécution. Elles sont à privilégier pour vérifier une situation externe (d'origine) sur laquelle nous n'avons pas de contrôle depuis le code.

                  Une assertion est là pour indiquer que si elle n'est pas remplie il y a alors une erreur de conception/programmation et qu'il n'est pas possible de continuer car on n'a pas prévu le code pour résister à la situation. En cas de supposition non remplie, selon le mode d'exécution, on plante le programme et on force le développeur à corriger son erreur, ou on continue car on pense qu'il n'y a plus lieu d'impacter les performances à vérifier dynamiquement toutes les situations impossibles.

                  La difficulté est de trouver la frontière entre les deux. Je creuse la question dans mes billets de blog.

                  Dans tous les cas, un log ne suffit pas à arrêter de continuer quand on sait que la situation est anormale.

                  -
                  Edité par lmghs 17 février 2020 à 12:01:44

                  • Partager sur Facebook
                  • Partager sur Twitter
                  C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                    17 février 2020 à 12:39:14

                    • Partager sur Facebook
                    • Partager sur Twitter
                    Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                      17 février 2020 à 12:55:16

                      Dans ton cas, on peut certes créer une log, cependant, il faut penser à propager l'exception, faute de quoi, elle est considérée comme traitée et la propagation de cette dernière est interrompue, ce qui n'est pas désirable.

                      De plus, même si l'intention est louable, elle possède un gros inconvénient:
                      La prolifération des blocs try / catch peut sévèrement nuire à la lisibilité de ton code source.
                      Donc: A utiliser avec parcimonie.

                      • Partager sur Facebook
                      • Partager sur Twitter
                        17 février 2020 à 13:17:53

                        N'abuse pas de la programmation défensive. Une fonction doit faire le minimum et ce n'est pas à elle de vérifier que tout ce qui est passé en entrée est juste.

                        Si la valeur peut venir de l'utilisateur, c'est au moment où tu fais la saisie que tu dois faire la vérification. La fonction elle n'a que faire de savoir de où la valeur vient.

                        En revanche, une assertion peut-être bienvenue pour détecter les erreurs de programmation pendant le développement.

                        -
                        Edité par markand 17 février 2020 à 13:22:19

                        • Partager sur Facebook
                        • Partager sur Twitter

                        git is great because Linus did it, mercurial is better because he didn't.

                          17 février 2020 à 13:50:46

                          Bon je potasse tout ça, je reviens vers vous au besoin.

                          Merci pour vos retour.

                          A+

                          • Partager sur Facebook
                          • Partager sur Twitter
                            18 février 2020 à 2:02:20

                            > Attendons les plus calés, mais pour moi si tu utilise try tu peux meme faire des trucs comme des acces hors tableau ça ne plante pas l’appli alors que le deuxieme exemple peux te planter toute l’appli

                            Je réagis juste sur ça. Un accès hors tableau est toujours un problème et cause d'erreur. Contrairement à certains langages, il n'y a pas magiquement d'exception dans un tel scénario, c'est au développeur de vérifier le dépassement et de lancer une exception. Donc, pour qu'une exception arrive, il faut déjà faire cette vérification. Et après vient tout le débat sur programmation défensive vs programmation par contrat expliqué dans les articles de @lmghs

                            • Partager sur Facebook
                            • Partager sur Twitter
                              18 février 2020 à 11:58:58

                              Je parlais des hors tableau car pour moi le try catch sert surtt pendant le dev, mais c’est pe etre une simplification négative de ma part.
                              • Partager sur Facebook
                              • Partager sur Twitter
                                18 février 2020 à 12:38:21

                                Ca sert à revenir à un point de reprise: on indique à l'utilisateur que sa donnée est foireuse et on lui permet de recommencer.
                                • Partager sur Facebook
                                • Partager sur Twitter
                                C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                                  18 février 2020 à 13:01:00

                                  JeromeHumbert2 a écrit:

                                  Je parlais des hors tableau car pour moi le try catch sert surtt pendant le dev, mais c’est pe etre une simplification négative de ma part.


                                  Non, la raison d'être des exception est prendre en charge les évènements sur lesquels tu n'as aucun contrôle.
                                  Par exemple une allocation dynamique qui foire, ou une connection à une base de données qui saute.
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    12 mars 2021 à 10:48:24

                                    Bonjour à tous,

                                    Je reviens vers vous car j'ai toujours pas compris l'intérêt des exceptions. Peut être parce que dans mon code je n'en ai pas besoin.

                                    Je reprends mon exemple en post1, quel intérêt d'implémenter une exception alors qu'un if else permet de faire la même chose?

                                    Pouvez-vous me donner des exemples d'utilisation pertinents?

                                    Merci

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      12 mars 2021 à 12:56:13

                                      C'est un sujet sujet à débat.

                                      Le thème chapeau: "que faire en situation anormale de type le monde m'en veut?". Par "le monde m'en veut", il faut comprendre: toutes ces erreurs liées à l'environnement sur lesquelles on ne peut avoir aucun contrôle par programmation: fichier/BD incorrect(/e) ou corrompu(/e), disque plein, plus de mémoire, connexion internet coupée à cause d'une tempête alors que l'on communiquait par socket, utilisateur qui dit n'importe quoi comme "chaussette" quand on lui demande son niveau etc.

                                      Bref, il y a des erreurs externes. Ces erreurs il faut les faire remonter jusqu'à un moment où l'on pourra faire quelque chose avec notre programme: proposer de recommencer, dire "désolé nous allons devoir interrompre la suite de nos programmes veuillez revenir plus tard". Bref, interrompre le flot d'exécution nominal et se mettre à un point neutre (il doit y avoir un terme officiel) relativement à ce que l'utilisateur voudra faire.

                                      Comment on remonte?

                                      1- en cascadant les "if (error) return errorcode". Ce genre de programme doit avoir environ un if toutes les deux lignes pour être correct (je passe le lien vers l'article d'Aaron Lahman traduit par Alexandre Laurent sur dvpz). Si on oublie de vérifier un retour possiblement anormal pour continuer de propager l'erreur jusqu'au point neutre, on pourra vite se retrouver avec un programme au comportement complètement incompréhensible car buggué. Et oui on peut oublier de propager une situation anormale car on n'est pas obligé de rattraper un résultat de fonction en C, Java, Python, C++... Oublier les if, c'est le pays magique où les erreurs n'existent pas, c'est celui qui est enseigné trop souvent en premier de peur de faire peur aux débutants (au lieu de choisir les bons constructs en C++ comme le RAII...)

                                      Accessoirement, le code assembleur généré pour code correct avec un if toutes les deux lignes va être parasité de branchements pour remonter les possibles erreurs. Ce n'est bon ni pour la prédiction de branches, ni pour le cache d'instructions. À noter que ce code, correct, parasité par un if toutes les deux lignes; sera lourd et difficile à maintenir. Même avec des macros.

                                      2- en lançant une exception qui remonte toute la pile jusqu'au point neutre. Si on oublie le catch, l'exception remonte. Possiblement c'est exactement ce que l'on veut. Le code à maintenir est simple. Les chemins nominaux sont rapides. Le code est correct grâce au RAII (dans d'autres langages ce sera grâce à finally, ou encore au try-with-ressources (Java), using (C#), with (Python)...).

                                      Par contre si une erreur est détectée, propager une exception devient très cher.

                                      3- Des aficionados du fonctionnel sont "en train" d'importer des monades (cf boost.outcome) en C++ pour essayer de pallier aux faiblesses d'oubli potentiel du modèle de propagation manuel, sans imposer les exceptions à ceux qui n'aiment pas ça parce que trop magique.

                                      <subjectif on>Perso, je ne suis pas entièrement convaincu. On a toujours un if toutes les deux lignes, mais l'avantage est que l'on ne peut pas l'oublier sinon cela ne compilera pas. Et donc il y a aussi parasitage du cache. Autre point négatif  mon goût, c'est l'absence de support par le langage qui nous oblige toujours à explicitement avoir un if (ou macro) toutes les deux lignes. Bref, il y a toujours cette extra verbosité, parfois étrange grâce aux macros "simplificatrices".</>

                                      Comment choisir?

                                      Personnellement, c'est exception par défaut. Mais si le nombre de niveaux à remonter est extrêmement court (0 ou 1), et/ou que les "erreurs" de contexte à gérer sont excessivement plausibles, je vais passer par une propagation avec des branches explicites.

                                      Exemple?

                                      Ici, dans un code de tic-tac-toe (de dimension quelconque), L'utilisateur peut choisir d'abandonner la partie https://github.com/LucHermitte/tictactoe/blob/master/tictactoe.cpp#L605, lors de sa saisie clavier et cette situation sera remontée tout en haut. Je te laisse l'exercice d'identifier les niveaux intermédiaires et comment le code aurait dû être modifié pour remonter proprement la volonté de mettre un terme à la partie jusqu'au main(). Certes, le choix a été fait d’arrêter le programme. Mais dans d'autres média que la console, on aurait proposé une autre partie. (je sais j'ai complètement dévoyé les exceptions ici, ceci dit j'ai interprété une perte du canal de comm avec le joueur comme une volonté d'arrêt, mais techniquement, on ne peut vraiment plus communiquer avec le joueur, ce qui est un problème de contexte majeur)

                                      A noter, que toutes les allocations sont aussi susceptibles de lancer des exceptions. On ne voit pas leurs `throw`mais ils sont là à chaque new, à chaque création de std::string, std::vector...

                                      -
                                      Edité par lmghs 12 mars 2021 à 13:16:07

                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                      C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                                        12 mars 2021 à 14:38:17

                                        Salut lmghs, je suis allé voir ton billet de blog sur la programmation par contrat et il me semble avoir repérer une petite coquille.

                                        Dans le billet 1/3 : https://luchermitte.github.io/blog/2014/05/24/programmation-par-contrat-un-peu-de-theorie/

                                        Début de partie II :

                                        Par exemple, la fonction sqrt(x) ne prend que des paramètres numériques positifs x, et elle renvoie des nombres toujours positifs qui vérifient result = x².

                                        result = sqrt(x) <==>  result = √x  <==>  result² = x 


                                        Billet de blog très intéressant à lire en tout cas merci pour ton travail ;)

                                        -
                                        Edité par ThibaultVnt 12 mars 2021 à 14:38:31

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          12 mars 2021 à 15:00:21

                                          Merci ThibaultVnt. Et zut, il va falloir que je retrouve comment maintenir les billets sur cette nouvelle machine maintenant ^^'
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                          C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                                            13 mars 2021 à 3:18:18

                                            Daimyo_ a écrit:

                                            "unsigned" existe aussi.


                                            Tu veux parler du premier message? Malheureusement, Avec le code montré, cela pourrait cacher des erreurs potentiellement très compliqués à trouver sans outillage

                                            void f(unsigned);
                                            .
                                            .
                                            .
                                            f(-2);



                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                            C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                                              13 mars 2021 à 11:52:08

                                              Oups... J'avais visiblement oublié que le typage permettait de convertir implicitement un non-signé vers un signé.

                                              Des souvenirs d'autres langages...

                                              • Partager sur Facebook
                                              • Partager sur Twitter

                                              Exception et fichier de LOG

                                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                              • Editeur
                                              • Markdown