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 :

bug clang boucle infinie


Sujet :

C

  1. #1
    Futur Membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Juin 2021
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 22
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2021
    Messages : 8
    Points : 6
    Points
    6
    Par défaut bug clang boucle infinie
    alut à toutes et tous

    j'ai un code qui fonctione en debug mais pas en optimisé et uniquement avec clang pas avec gcc. je voulais savoir votre avis si c'est un bug ou si c'est normal ou je sais pas. j'ai fait un code minimal pour vous faire la demo.

    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
    18
    19
    20
     
    #include <stdio.h>
     
    int test()
    {
        while(1)
        {
            for(int i=10; i<100; i++)
                if ( i*i > i*i*i )
                    return 1;
        }
        return 0;
    }
     
    int main()
    {
        printf("On test : ");
        if (test()) printf("VRAI\n");
        else        printf("FAUX\n");
    }
    comme un carré est toujours plus petit qu'un cube si c'est plus grand que 10 je dois jamais sortir du while et ca doit tourné en rond. c'est ce que ça fait avec clang en mode debug mais si je demande un O3 alors ça plante plus et ça m'affiche vrai.

    je compile avec clang comme ça

    clang -Werror -Wall -Wextra -O3 -o simple_clang_O3 simple.c et clang -Werror -Wall -Wextra -g -o simple_clang_g simple.c

    j'ai pas de message et si je lance simple_clang_O3 il m'affiche On test : VRAI et il m'affiche rien avec l'autre et s'arrête pas.

    ca le fait pas avec gcc.

    vous avez des idées ? le O3 de clang est cassé et je dois plus l'utilisé ou je passe avec gcc qui est plus sure ?

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    gcc optimise surement en laissant le while infini tandis que clang le vire puisqu'il est vide.
    Il faut comparer le code généré.
    L'erreur c'est surtout ce code. Mais il devrait afficher faux imo.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Futur Membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Juin 2021
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 22
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2021
    Messages : 8
    Points : 6
    Points
    6
    Par défaut
    le code c'est une demo minimaliste. je vais pas copier tout le code que j'ai. ça fait que reproduire une erreur.
    alors non c'est une boucle infinie donc ça doit boucler. le comportement est ok sans O3 mais avec O3 ça donne un programme qui fait pas le code. pour moi c'est un bug.

  4. #4
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Le problème est reproductible sur Compiler Explorer avec les dernières versions de chaque compilateur : https://godbolt.org/z/63G7Pe5GY

    Une versions sans printf() est plus simple si on souhaite analyser l'assembleur pour comprendre ce qu'il se passe (je n'ai pas fait cet effort):

    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
    int test()
    {
        while(1)
        {
            for(int i=10; i<100; i++)
                if ( i*i > i*i*i )
                    return 1;
        }
        return 0;
    }
     
    int main()
    {
        return test();
    }
    Le problème ne semble pas venir d'O3 en lui-même : ça semble tourner en rond de la même manière quelque soit le niveau d'optimisation. Du coup je me demande si ça se passe bien quand on compile qq chose avec GCC sur Compiler Explorer. --> j'ai essayé avec fonction test() qui fait un simple return 0; et ça compile et s'exécute correctement. Ca vient donc bien de ton sample, dans lequel je ne vois pas de problème.

  5. #5
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    Bonjour,

    L'analyse qui est peut-être faite par l'optimiseur:
    - Il n'y a aucun effet de de bord dans la fonction
    - toutes les données sont des constantes
    - donc il y a une solution qui peut entièrement se résoudre à la compilation
    - la fonction s'engage à retourner un entier, 2 possibilités dans le code : retourner 0 ou retourner 1.
    - ça ne peut pas être 0 car il est après un while sans sortie.
    - seule possibilité : la fonction doit retourner 1.
    Le seul détail oublié c'est qu'il faut un temps infini avant de retourner 1. Mais pourtant cette fonction ne peut que retourner 1.

  6. #6
    Membre éclairé
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Septembre 2015
    Messages
    204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte de système d'information

    Informations forums :
    Inscription : Septembre 2015
    Messages : 204
    Points : 839
    Points
    839
    Par défaut
    pour le code généré, vous pouvez regarder sur le site suivant : https://godbolt.org/

    on voit bien que pour clang, il transforme la méthode en return 1 !

    alors qu'avec gcc, on ne voit pas le return 0; mais on "voit" la boucle sans fin

  7. #7
    Futur Membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Juin 2021
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 22
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2021
    Messages : 8
    Points : 6
    Points
    6
    Par défaut
    rholala ... le code est une demo minimaliste qui montre le même problème que j'ai avec un code plus long et que j'ai trouvé le bug. c'est pas un code qui est in reel life. tout ce que je veux savoir c'est si c'est un bug ou non le programme que clang donne avec O3.
    sur un autre forum c'est pareil on dit que mon code c'est de la merde mais c'est juste un exemple les gars.
    donc il y en a deux qui dise que c'est un bug parceque le comportement change entre optimisé et pas optimisé et d'autre qui disent que non que
    les "optimisations" faites par les compilateurs ne préservent malheureusement pas la sémantique. Et sont donc, pour la plupart, fausses (parce qu'elles font l'impasse sur des cas plus ou moins tordus).
    ma question est pas compliqué, si on lit le code et que ça doit boucler à l'infini et que ça donne un programme qui boucle pas c'est que clang a un bug. je me trompe ?

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Minimal ou pas, oui le code est mauvais.
    Si tu veux une boucle infinie, tu écris une boucle infinie. Et sois assurée que t'es pas la première à vouloir en écrire une, donc les chances que tu aies trouvé un bug du compilateur sont ultra minces.
    Là tu as une boucle infinie, une boucle inutile et un test impossible. Minimale ou pas, si ton code réel a la même boucle inutile et test impossible, c'est ce qu'on appelle communément un mauvais code.
    Et un compilateur il fait pas de miracles. Il fait de son mieux pour donner du sens à tout ça.
    Va donc faire un bug report à l'équipe de Clang si c'est ce que tu penses. Ils sauront bien mieux que nous ce qui se passe et pourquoi.

    Le seul détail oublié c'est qu'il faut un temps infini avant de retourner 1. Mais pourtant cette fonction ne peut que retourner 1.
    J'aurais justement misé sur return 0 après un tems infini : le return 1 est impossible à atteindre.
    Mais le return 0 aussi en théorie.
    Donc, à code tordus, on peut imaginer pas mal de choses.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  9. #9
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Minimal ou pas, oui le code est mauvais.
    Bof syntaxiquement c'est correct (le code compile) et il n'y a rien de tordu (pas de pointeur, pas d'optimisations, pas de #define ...)

    Que le code "tourne en rond", ce n'est pas 1 qualité (bon ou mauvais) - c'est 1 code faux c'est tout
    Mauvais code, c'est 1 jugement personnel d'humain


    Citation Envoyé par Bousk Voir le message
    Et un compilateur il fait pas de miracles. Il fait de son mieux pour donner du sens à tout ça.
    Encore 1 fois, le code c'est 2 boucles et 1 test Le compilateur n'est pas humain pour émettre 1 jugement et ne doit pas "faire de la m*rde" si le code est mauvais/ faux/ ...
    On doit retrouver au moins 1 trace dans le code résultat des structures de contrôle.

    Et pour moi, j'ai déjà fait ce genre de code . On a 1 idée et on commence à coder, et à 1 moment, + on empile les tests/ boucles, + on est fier en se disant "bouah comme c'est difficile".
    Et très très souvent après X relectures, on se dit "ouais, le code est en simple, que je suis bête d'être parti aussi loin"


    Citation Envoyé par Bousk Voir le message
    J'aurais justement misé sur return 0 après un tems infini : le return 1 est impossible à atteindre.
    Mais le return 0 aussi en théorie.
    Donc, à code tordus, on peut imaginer pas mal de choses.
    Je pense à 1 problème de l'automate/ machines à états Ce code a 2 chemins,
    • début -> while -> for -> if -> return 1
    • début -> while -> return 0

    Mais apparemment, la simplification semble simple (même début et même fin) : début -> while [[optionnel: -> for -> if ]] -> return 1 ou return 0.
    Or il ne peut pas simplifier ainsi parce que le return 1 est à l'intérieur du while - le return 0 est à l'extérieur du while

  10. #10
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par foetus Voir le message
    Encore 1 fois, le code c'est 2 boucles et 1 test
    Mais une de ces boucles est inutile et va juste boucler pour réaliser un test impossible et donc tout autant inutile.
    Je vois pas ce qu'il te faut de plus pour qualifier un code de mauvais...
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  11. #11
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Mais une de ces boucles est inutile et va juste boucler pour réaliser un test impossible et donc tout autant inutile.
    Je vois pas ce qu'il te faut de plus pour qualifier un code de mauvais...
    1 code mauvais, c'est 1 code plantogène (pointeur non initialisé, débordement, manque de paramètres, ...), qui manque des tests défensifs voire ayant des optimisations douteuses.

    C'est 1 code faux, parce que le code fait 1 boucle infinie : en théorie, les tests doivent détecter son comportement erroné.

    Donc voila, fin du débat pour reprendre mon exemple "pris dans son code", toi tu fais partie des développeurs qui codent à 100% juste sans aucune erreur quelle qu'elle soit, et que donc tu ne trouves pas "anormal" (parce que cela ne t'arrive jamais) que le compilateur fasse n'importe quoi parce qu'il ne te laisse pas coder des codes faux (<- moi je pense plutôt à "1 trou dans la raquette" niveau optimisation, dans le sens 1 cas non pris en charge ou 1 effet de bord)

  12. #12
    Membre expérimenté
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Juillet 2020
    Messages
    352
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Juillet 2020
    Messages : 352
    Points : 1 376
    Points
    1 376
    Par défaut
    Hello,

    Peu importe la qualité ou le jugement émit sur le code, clang se plante dans sa production d'exécutable.

    Si un code source code une boucle infinie (volontairement ou pas), alors le programme doit boucler indéfiniment. clang le fait si on ne lui demande pas d'optimiser, il ne le fait pas dès qu'on lui demande d'optimiser.
    Conclusion : les optimisations agressives de clang dès -O font que l'exécutable produit n'est pas conforme au source. clang est bugué.

  13. #13
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    Bonjour,

    On peut poser que c'est un bug. Mais il faut revenir au rôle de l'optimiseur, il doit produire ce que le code demande. Donc un code qui ne contient pas d'undefined behaviour devrait donner la même sortie quelle que soit l'optimisation.
    Le problème de la boucle infinie est que : "il est impossible de prédire de manière certaine qu'une boucle est infinie ou pas dans tous les codes". La phrase parait forte et pourtant ça se prouve simplement.
    Si on revient à l'exemple. Je le modifie un peu:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int test() {
        while(1) {
            for(int i=10; i<INT_MAX; i++) 
                if ( i*i > i*i*i )  // il existe peut-être des cas pour lesquels ce test est vrai
                    return 1;
        }
        return 0;
    }
    Que doit produire l'optimiseur dans ce cas? Est-ce que retourner 1 n'est pas la bonne solution? C'est moins évident!
    Il est vrai que comme l'expression est simple, la boucle infinie était la solution du premier cas. Retourner 1 est vraisemblablement la solution du second.
    Ce que l'on peut reprocher à l'optimiseur c'est ne pas avoir analysé la boucle infinie. Mais comme une boucle infinie n'est pas toujours détectable, comment être sûr du résultat après optimisation?
    Et donc pour être sûr de gérer correctement les boucles infinies, il existe un moyen simple : demander à ne pas optimiser!

  14. #14
    Membre expérimenté
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Juillet 2020
    Messages
    352
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Juillet 2020
    Messages : 352
    Points : 1 376
    Points
    1 376
    Par défaut
    Citation Envoyé par dalfab Voir le message
    [...]
    Il est vrai que comme l'expression est simple, la boucle infinie était la solution du premier cas. Retourner 1 est vraisemblablement la solution du second.
    Ce que l'on peut reprocher à l'optimiseur c'est ne pas avoir analysé la boucle infinie. Mais comme une boucle infinie n'est pas toujours détectable, comment être sûr du résultat après optimisation?
    Et donc pour être sûr de gérer correctement les boucles infinies, il existe un moyen simple : demander à ne pas optimiser!
    C'est clair que détecter les boucles infinies revient au problème de l'arrêt, c'est donc indécidable.
    Maintenant c'est peut-être un point de vue particulier, mais à la question de comment «être sûr de gérer correctement les boucles infinies», le moyen le plus simple qui me vient à l'esprit est : l'optimiseur ne devrait pas s'en occuper et ne pas les optimiser même si l'utilisateur demande une version optimisée. Cela a au moins l'avantage de produire un code correct.

  15. #15
    Membre expérimenté
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    543
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 543
    Points : 1 745
    Points
    1 745
    Par défaut
    Bonsoir,
    Citation Envoyé par LucyFayry Voir le message
    ma question est pas compliqué, si on lit le code et que ça doit boucler à l'infini et que ça donne un programme qui boucle pas c'est que clang a un bug. je me trompe ?

    Ce n’est pas un bug de la part de l’optimiseur du compilateur clang; ni ce que l’on peut considérer comme étant un comportement indéterminé ou supposer que le code est erroné. C’est un effet non souhaité à cause d’un code mort / inutile (dead code).

    Il faut comprendre que le rôle de l’optimiser d’un compilateur n’est pas d’optimiser au sens strict ; mais d'améliorer les performances ou la taille du code au détriment du temps de compilation et de la possibilité de déboguer.

    Dans le cas actuel, l’optimiseur du compilateur est dans son droit, car les règles de l’optimiseur considèrent le code de la fonction « teste » comme étant du code mort à cause de certains calculs inutiles ou redondants. Plus précisément dus au fait que l’expressions (ligne if) calculent la même valeur et donc pour l’optimiseur cela signifie qu’une valeur est calculée plusieurs fois et/ou à des endroits relativement proches, par des suites d’instructions séparées.

    D’ailleurs dans la fonction main, il me semble que la fonction considérée code mort n’est pas appeler.
    Exemple clang -S -emit-llvm -O3 debug_front_end_suspect.c
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    ; Function Attrs: nofree nounwind ssp uwtable                                                                                            
    define i32 @main() local_unnamed_addr #1 {                                                                                                 
     %1 = tail call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i64 0, i64 0)) 
    %2 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([5 x i8], [5 x i8]* @str, i64 0, i64 0))                  
     ret i32 0                                                                                                                                 
    }                                                                                                                                 
    ; Function Attrs: nofree nounwind                                                                                                          
    declare i32 @printf(i8* nocapture readonly, ...) local_unnamed_addr #2                                                                     
    ; Function Attrs: nofree nounwind                                                                                                        
    declare i32 @puts(i8* nocapture readonly) local_unnamed_addr #3
    à bientôt
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  16. #16
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Citation Envoyé par sambia39 Voir le message
    C’est un effet non souhaité à cause d’un code mort / inutile (dead code).
    Du code mort il y a le return qui même s'il est inatteignable, dit que cette branche peut être exécutée while -> for -> if -> return 1.

    Le seul truc c'est que l'analyseur/ compilateur teste toutes les 99 valeurs pour juger que le test est toujours faux (<- cela peut-être 1 truc bête comme le compilo isole le code et l'exécute avec 1 timeout)
    C'est vrai que le code/ bloc for a très peu de lignes de code et ne fait pas appel à des variables externes (1 seul if et 1 return) et que l'analyseur/ compilateur peut se dire "je peux optimiser".
    Mais dans ce cas, les analyseurs/ compilateurs deviennent de + en + complexes

    Et c'est toujours le problème de ce fil : même si le code/ bloc for est du code mort, il reste la boucle infinie while qui ne doit pas disparaître.

  17. #17
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Pour info : j'ai repris mon exemple sur Compiler Explorer (dont le lien est dans mon précédent message) et j'ai choisi C++ au lieu de C comme langage => clang comme gcc font des boucles infinis.

    L'explication de @dalfab est très séduisante. Si je devais parier, je dirais que c'est effectivement ce qu'il se passe.

    Il me vient hypothèse en tête : il y aurait un UB qui dirait "tu ne peux pas faire de return dans une fonction s'il y a une boucle infinie". Si tel est le cas, ça expliquerait une différence de comportement entre C et C++ (en admettant que l'UB soit présent dans les 2 langages). Ca expliquerait que le comportement en C avec optimisation n'est pas celui attendu.

    Si un tel UB n'existe pas, j'ai envie de dire qu'il y a un bug dans clang.

    EDIT : https://stackoverflow.com/questions/...infinite-loops Cette discussion stackoverlow peut donner des réflexions sur ce qui est possible ou pas de faire.

  18. #18
    Futur Membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Juin 2021
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 22
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2021
    Messages : 8
    Points : 6
    Points
    6
    Par défaut
    merci tt le monde

    je retiens ça : gcc a un comportement constant et cohérent, clang non. clang a un bug qui n'est pas un bug mais qui fait ièch parceque c'est un bug quand même. la plupart d'entre vous défendes le compilo en disant que mon code est de la merde mais c'est qu'un code démo. les autres sont moins fermé

    je ferme mon sujet car j'ai mes réponses

    merci pour vos efforts

  19. #19
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Citation Envoyé par WhiteCrow Voir le message
    Si un code source code une boucle infinie (volontairement ou pas), alors le programme doit boucler indéfiniment. clang le fait si on ne lui demande pas d'optimiser, il ne le fait pas dès qu'on lui demande d'optimiser.
    Conclusion : les optimisations agressives de clang dès -O font que l'exécutable produit n'est pas conforme au source. clang est bugué.
    Ca me semble assez irréfutable. Le minimum qu'on est en droit d'attendre d'un compilateur est qu'il reproduise en toutes circonstances fidèlement l'algorithme qu'on lui donne. C'est d'ailleurs écrit en introduction d'un des tutoriels de ce site qui dit, en parlant du compilateur: "Fondamentalement, c'est une traduction : un texte écrit en Pascal, C, Java, etc., exprime un algorithme et il s'agit de produire un autre texte, spécifiant le même algorithme dans le langage d'une machine que nous cherchons à programmer."

    Citation Envoyé par dalfab Voir le message
    if ( i*i > i*i*i ) // il existe peut-être des cas pour lesquels ce test est vrai
    Mathématiquement oui, quand 0 < i < 1, ou bien quand i < 0. On peut aussi avoir le cas en C quand i dépasse une certaine limite (que j'ai la flemme de calculer). Comme il est signé, son carré (positif) sera plus grand que son cube (passé en négatif du fait de la bascule de son bit de signe).

    Le site officiel possède un outil de bug reports. Peut-être leur soumettre le problème...

    Citation Envoyé par foetus Voir le message
    même si le code/ bloc for est du code mort, il reste la boucle infinie while qui ne doit pas disparaître.
    Tout à fait d'accord. Et en plus je ne vois pas pourquoi on irait dire que ce bloc est mort. Suffit de rajouter un printf() dans la boucle interne et on verra bien qu'elle tourne...

    Citation Envoyé par Bktero Voir le message
    Il me vient hypothèse en tête : il y aurait un UB qui dirait "tu ne peux pas faire de return dans une fonction s'il y a une boucle infinie".
    Cela foutrait en l'air 90% des codes de la planète

    [edit]Je suis un peu revenu sur ce code. En partant de l'hypothèse que la boucle interne ne sert à rien (je pense que tout le monde sera d'accord là dessus), je l'ai supprimée et l'ai remplacée par un random
    Code c : 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
    18
    19
    20
    #include <stdio.h>
    #include <stdlib.h>
     
    int test()
    {
    	unsigned short i;
    	while(1)
    	{
    		i=rand() % 1000 + 1;
    		if ( i*i > i*i*i ) return 1;
    	}
    	return 0;
    }
     
    int main()
    {
    	printf("On test : ");
    	if (test()) printf("VRAI\n");
    	else		printf("FAUX\n");
    }
    Et là, plus de bug. Le programme tourne et tourne encore jusqu'à ce que je le kille. Le souci semble donc lié à la façon dont clang analyse l'imbrication des deux boucles...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  20. #20
    Membre expérimenté
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Juillet 2020
    Messages
    352
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Juillet 2020
    Messages : 352
    Points : 1 376
    Points
    1 376
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    [...]
    Le site officiel possède un outil de bug reports. Peut-être leur soumettre le problème...
    Hello,
    oui, le premier BR date de 2006 c'est le BR965, 10 autres ont suivis. Le problème est partiellement résolu depuis avril 2021 avec LLVM 12.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. comment construire une boucle infinie sans bug
    Par stuffy dans le forum Général Python
    Réponses: 1
    Dernier message: 07/07/2008, 18h53
  2. Réponses: 15
    Dernier message: 24/05/2005, 08h34
  3. [Socket] Pb de boucle infinie
    Par Myogtha dans le forum Entrée/Sortie
    Réponses: 12
    Dernier message: 10/06/2004, 14h10
  4. [C#] Comment eviter les boucles infinies ?
    Par Thomas Lebrun dans le forum C#
    Réponses: 12
    Dernier message: 09/06/2004, 00h04

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