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 :

Bien quitter son programme


Sujet :

C

  1. #21
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Mais même s'ils le font, ils peuvent être moins performants dans ce cas. Windows notamment est optimisé pour le cas où les ressources sont libérées correctement; la libération "par l'OS" n'est pas forcément rapide.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  2. #22
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Points : 7 882
    Points
    7 882
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Mais même s'ils le font, ils peuvent être moins performants dans ce cas. Windows notamment est optimisé pour le cas où les ressources sont libérées correctement;
    Il s'agit ici de fenêtres qui ne sont pas détruites par une application avant de sortir. Le gestionnaire de fenêtres (Windows en l'occurence) ne se termine pas et doit donc libérer sa propre mémoire. Ca n'a pas vraiment de lien avec la question. Avec Windows comme avec tous les OS qui se respectent, embarqués ou pas, la mémoire d'un processus terminé est libérée.
    la libération "par l'OS" n'est pas forcément rapide.
    Non seulement cette libération par l'OS est rapide, mais elle est en fait plus rapide que lorsque c'est le programme qui l'effectue avant de se terminer.

    En effet, un processus qui libère la mémoire qu'il a alloué doit faire un appel à free pour chaque pointeur. Chaque appel va nécessiter des contrôles et des écritures, ce qui peut être non négligeable si on a alloué des milliers/millions de blocs mémoire.

    En revanche, qu'elle ait été libérée par programme ou pas, l'OS va libérer "d'un coup" la totalité de la mémoire virtuelle mappée en RAM ou dans le swap sans se poser de questions.

    Edit: Bien sûr, ne pas prendre ma réponse pour un encouragement à ne pas libérer la mémoire allouée lorsqu'elle n'est plus nécessaire !
    ɹǝsn *sıɹɐlos*

  3. #23
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 150
    Points : 28 119
    Points
    28 119
    Par défaut
    Citation Envoyé par Neckara Voir le message
    On a jamais dit de ne pas libérer soit-même la mémoire, juste que si il y a une petite fuite de mémoire (ce qui peut arriver et que atexit() était censé nous éviter), ce n'est pas très "grave" (vu que l'OS est censé libérer la mémoire)
    Justement non :
    Citation Envoyé par skeud Voir le message
    Si c'est un one-shot, tu n'as pas trop besoin de t'occuper de libérer la mémoire, elle sera automatiquement libérer lors de l'arret, donc ça règle la question.

    C'est cette phrase qui m'a fait bondir (ou presque) de ma chaise, et qui fait que je recommande de bien gerer sa memoire, ce qui inclue sa liberation.
    "La route est longue, mais le chemin est libre" -- https://framasoft.org/
    Les règles du forum

  4. #24
    Membre émérite
    Avatar de skeud
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2011
    Messages
    1 091
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 1 091
    Points : 2 724
    Points
    2 724
    Billets dans le blog
    1
    Par défaut
    Pour reprendre ce que j'ai dis, effectivement, ne pas libérer la mémoire et compter sur l'OS pour la libérer c'est pas top, clairement.

    Ensuite, un OS doit OBLIGATOIREMENT libérer la mémoire à la fin d'un programme, peu importe ce qu'il se passe.
    Prenons un exemple:
    J'ai mon ptit OS sur un periph embarqué avec 56k de ram.
    Je bidouille un peu avec mon prog, y consomme 22k de ram, jcommence à être un peu juste et la paf, un tit segfault pour x raison.
    Imaginez si à ce moment la l'OS ne libère pas la mémoire, beh du coup on peu plus rien faire ......
    Donc oui c'est pas une bonne pratique de ne pas libérer la mémoire au fur et a mesure qu'on l'utilise.
    Mais non, c'est pas un drame si on ne le fait pas pour des programmes One-shot (chose que la plupart ont oubliés de lire apparemment .

    Dans une grosse société dont je ne dirais pas le nom, où je bosse, on fonctionne exclusivement avec des prog one-shot qui vont allouer pas mal de petit bloc de mémoire qui seront utiles tout le long du traitement.

    Et dans des soucis d'optimisation, on ne libère pas la mémoire, on laisse l'OS s'en charger car il sera beaucoup plus rapide que nous pour retrouver les plage mémoires allouées.
    Pas de solution, pas de probleme

    Une réponse utile (ou +1) ->
    Une réponse inutile ou pas d'accord -> et expliquer pourquoi
    Une réponse à votre question


  5. #25
    Membre habitué Avatar de dafpp
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 345
    Points : 196
    Points
    196
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    1)
    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    void fonction()
    {
        char *buf1;
        char *buf2;
        char *buf3;
     
        buf1=malloc(...)
        if (buf1 == NULL)
            return;
     
        buf2=malloc(...)
        if (buf2 == NULL)
        {
            free(buf1);
            return;
        }
     
        buf3=malloc(...)
        if (buf3 == NULL)
        {
            free(buf1);
            free(buf2);
            return;
        }
     
        .... // travail
        free(buf1);
        free(buf2);
        free(buf3);
    }
    2)
    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
    21
    22
    23
    int fonction()
    {
        char *buf1;
        char *buf2;
        char *buf3;
     
        buf1=malloc(...)
        if (buf1 != NULL)
        {
            buf2=malloc(...)
            if (buf2 != NULL)
            {
                buf3=malloc(...)
                if (buf3 != NULL)
                {
                    .... // travail
                    free(buf3);
                }
                free(buf2);
            }
            free(buf1);
        }
    }
    3)
    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
    int fonction()
    {
        char *buf1=NULL;
        char *buf2=NULL;
        char *buf3=NULL;
     
        buf1=malloc(...)
        buf2=malloc(...)
        buf3=malloc(...)
        if (buf1 == NULL  || buf2 == NULL || buf3 == NULL)
            goto clean;
     
        .... // travail
     
        // Nettoyage
        clean:
        free(buf1);
        free(buf2);
        free(buf3);
    }
    Mon problème lors du post, c'est la 1. D'où le fait que je crée un nouveau topic : c'est redondant, et on peut oublier des pointeurs avec de la mémoire allouait.
    Après c'est vrai j'ai pensé à la deuxième, mais c'est lourd au niveau de la lecture du code.
    Moi je suis pour la 3e. C'est la même chose que la deux, mais en plus clair. Car si on voit ça en bas niveau, il y a rien de mal à utiliser goto. (?) Donc j'utilise une variable pour le code retour de mon programme, et je l'utilise au return au final.
    Normalement il n'y a pas de mal si j'utilise dans le main plusieurs fois goto clean?

    C'est toujours un plaisir de poser des questions sur ce site (forum), c'est toujours très instructif. Merci à tous.

    Et je suis sur un très bon OS, je lui fais confiance.
    "Les spécialistes commencent par n'apprendre que ce qu'ils aiment et finissent par n'aimer que ce qu'ils ont appris." - Gilbert Cesbron
    "Si nous avons chacun un objet et que nous les echangeons, nous avons chacun un objet. Si nous avons chacun une idée et que nous les échangeons, nous avons chacun deux idées." - Proverbe Chinois.

  6. #26
    Membre habitué Avatar de dafpp
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 345
    Points : 196
    Points
    196
    Par défaut
    ouh! Je profite du topic, en relisant les commentaires, je vois (et c'est pas la première fois bien sûr) que pour tester si un pointeur est NULL, c'est écrit :
    Mais moi je fais toujours
    C'est grave docteur?
    "Les spécialistes commencent par n'apprendre que ce qu'ils aiment et finissent par n'aimer que ce qu'ils ont appris." - Gilbert Cesbron
    "Si nous avons chacun un objet et que nous les echangeons, nous avons chacun un objet. Si nous avons chacun une idée et que nous les échangeons, nous avons chacun deux idées." - Proverbe Chinois.

  7. #27
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Ce n'est pas en soi un problème (c'est parfaitement légal en C et C++, et ça a le même effet) mais c'est légèrement moins lisible (donc, moins maintenable).

    Si ta variable s'appelle (ou commence par) p, ça ne gène pas vraiment la lecture.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  8. #28
    Membre habitué Avatar de dafpp
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 345
    Points : 196
    Points
    196
    Par défaut
    oui je ne voyais pas les choses comme ça...
    "Les spécialistes commencent par n'apprendre que ce qu'ils aiment et finissent par n'aimer que ce qu'ils ont appris." - Gilbert Cesbron
    "Si nous avons chacun un objet et que nous les echangeons, nous avons chacun un objet. Si nous avons chacun une idée et que nous les échangeons, nous avons chacun deux idées." - Proverbe Chinois.

  9. #29
    Membre émérite
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    852
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 852
    Points : 2 298
    Points
    2 298
    Par défaut
    Citation Envoyé par dafpp Voir le message
    ouh! Je profite du topic, en relisant les commentaires, je vois (et c'est pas la première fois bien sûr) que pour tester si un pointeur est NULL, c'est écrit :
    Mais moi je fais toujours
    C'est grave docteur?
    A vrai dire il me semble avoir lu un post disant qu'en c++ il valait mieux ecrire :

    plutot que :

    Je cherche le topic et j'editerai ce post si j'arrive a le retrouver.

    Citation Envoyé par Médinoc
    Ce n'est pas en soi un problème (c'est parfaitement légal en C et C++, et ça a le même effet) mais c'est légèrement moins lisible (donc, moins maintenable).
    Je pense que c'est une question de pratique et / ou d'habitude a ce niveau la. Pour moi les deux comparaisons reviennent au meme et ne genent en rien la visibilite du code.

  10. #30
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 685
    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 685
    Points : 30 974
    Points
    30 974
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par dafpp Voir le message
    Mon problème lors du post, c'est la 1. D'où le fait que je crée un nouveau topic : c'est redondant, et on peut oublier des pointeurs avec de la mémoire allouait.
    Ben oui. La prog c'est aussi un peu de travail...

    Citation Envoyé par dafpp Voir le message
    Moi je suis pour la 3e. C'est la même chose que la deux, mais en plus clair. Car si on voit ça en bas niveau, il y a rien de mal à utiliser goto. (?)
    Il n'y a rien de mal à utiliser goto à bon escient. Sa mauvaise image vient du basic où il n'y avait que cette instruction qui donnait des programmes difficilements lisibles. Warnier a tenté une méthodologie basée sur cette instruction qui est ce qu'elle est mais bon, maintenant qu'il y a des whiles() et des for()...

    Citation Envoyé par dafpp Voir le message
    Donc j'utilise une variable pour le code retour de mon programme, et je l'utilise au return au final.
    Tu peux utiliser errno qui est là pour ça. Sauf si tu as peur d'une collision (elle est impactée à chaque appel system qui se passe mal)...

    Citation Envoyé par dafpp Voir le message
    Normalement il n'y a pas de mal si j'utilise dans le main plusieurs fois goto clean?
    J'espère que l'étiquette "clean" se trouve elle-aussi dans le main. Alors pas de souci si tu gardes à l'esprit que ce doit être une instruction exceptionnelle réservée à la gestion des erreurs. Maintenant moi j'ai une maxime personnelle pour ce genre de question : un bon programmeur respecte les règles ; un programmeur brillant les transgresse parfois...

    Citation Envoyé par dafpp Voir le message
    ouh! Je profite du topic, en relisant les commentaires, je vois (et c'est pas la première fois bien sûr) que pour tester si un pointeur est NULL, c'est écrit :
    Mais moi je fais toujours
    C'est grave docteur?
    Bah, est-ce que tu as peur de dépasser ton quota ? Sois large, aéré et explicite dans ton code. Au final l'optimiseur donnera le même exécutable mais quel plaisir de se relire facilement. et puis c'est tellement facile de se tromper et d'écrire if (p) au lieu de if (!p) et inversement alors que quand on écrit l'égalité explicite...
    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]

  11. #31
    Membre habitué Avatar de dafpp
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 345
    Points : 196
    Points
    196
    Par défaut
    Bah j'y pensais à errno, mais il y aura des erreurs qui viendront pas d'une histoire de système (comme erreur d'arguments, oublie d'argument, ...).

    Oui le clean se trouve tout à la fin du main, et j'ai retiré tous les exit() venant du main ou ailleurs, et je l'ai remplacé par goto clean;, avec bien sûr le changement de valeur pour la variable de retour.
    "Les spécialistes commencent par n'apprendre que ce qu'ils aiment et finissent par n'aimer que ce qu'ils ont appris." - Gilbert Cesbron
    "Si nous avons chacun un objet et que nous les echangeons, nous avons chacun un objet. Si nous avons chacun une idée et que nous les échangeons, nous avons chacun deux idées." - Proverbe Chinois.

  12. #32
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Bonjour,

    Pour if(!p) vs if(p == NULL), j'ai deux arguments en faveurs de if(!p) en C++ :
    - c'est plus court à écrire ;
    - on respecte le principe "d'encapsulation" pour les pointeurs "intelligents" :
    ---> On a pas à savoir l'adresse du pointeur ni s'il vaut NULL (nullptr en C++11) ou non. On a juste besoin de savoir s'il est valide ou non (ce qui n'est pas tout à fait la même chose ).

    Ensuite, pour le malloc, attention, sous Linux, par défaut, le malloc ne renverra jamais NULL. En effet l'allocation n'est réellement effectuée qu'à la première utilisation de l'espace alloué.

    Après, pour la libération de la mémoire, plutôt que de faire :
    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
    int fonction()
    {
        char *buf1=NULL;
        char *buf2=NULL;
        char *buf3=NULL;
     
        buf1=malloc(...)
        buf2=malloc(...)
        buf3=malloc(...)
        if (buf1 == NULL  || buf2 == NULL || buf3 == NULL)
            goto clean;
     
        .... // travail
     
        // Nettoyage
        clean:
        free(buf1);
        free(buf2);
        free(buf3);
    }
    On peut aussi faire :
    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
    21
    22
    #define Malloc(Z) ( alloc_it < alloc_max ? ( alloc[alloc_it++] = malloc(Z) ) : NULL )
    #define debutAlloc(SIZE) unsigned int alloc_it = 0; unsigned int alloc_max ; void * alloc[alloc_max = (SIZE)] = {NULL}
    #define finAlloc()  do{ for(int i= 0; i < XX ; ++i) \
               free(alloc[XX]); \
               while(0)
     
    void foo(void)
    {
          debutAlloc(50);
     
          int * toto = (int *)Malloc(sizeof(int) );
          if( ! toto )
          {
                    finAlloc();
                    puts(":cry:");
                    return;
          }
     
          // do some stuff
     
          finAlloc();
    }
    Ce qui pourrait être très pratique si tu as beaucoup d'allocations à faire.
    Les #define pourront être utile si tu veux faire la même chose dans plusieurs fonctions (ou pour frimer )

  13. #33
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 685
    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 685
    Points : 30 974
    Points
    30 974
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par dafpp Voir le message
    Bah j'y pensais à errno, mais il y aura des erreurs qui viendront pas d'une histoire de système (comme erreur d'arguments, oublie d'argument, ...).
    Non. Il est impacté par chaque appel système échoué (fopen, malloc, pipe, etc etc etc). Mais c'est conventionnel (chaque fonction a été codée pour le mettre à jour quand elle échoue).
    En revanche, un oubli d'arguments n'est pas un pb système mais un pb humain donc il n'est pas impacté.

    Citation Envoyé par Neckara Voir le message
    Bonjour,

    Pour if(!p) vs if(p == NULL), j'ai deux arguments en faveurs de if(!p) en C++ :
    - c'est plus court à écrire ;
    - on respecte le principe "d'encapsulation" pour les pointeurs "intelligents" :
    ---> On a pas à savoir l'adresse du pointeur ni s'il vaut NULL (nullptr en C++11) ou non. On a juste besoin de savoir s'il est valide ou non (ce qui n'est pas tout à fait la même chose ).
    Ah j'aime pas quand je lis ce genre de truc car je me sens dépassé et ça m'énerve. Bref en quoi "l'encapsulation" fonctionne avec if(!p) et ne fonctionne pas avec if (p == NULL) ? Et quelle différence entre "pointeur invalide" et "pointeur égal à NULL" ? malloc ne renvoie-t-elle pas NULL quand elle échoue ??? Parce que je ne teste pas "pointeur invalide" mais "pointeur égal à la valeur conventionnellement renvoyée par malloc en cas d'échec" ce qui n'est pas tout à fait la même chose dans la notion (même si c'est la même chose dans l'écriture)...

    Citation Envoyé par Neckara Voir le message
    Ensuite, pour le malloc, attention, sous Linux, par défaut, le malloc ne renverra jamais NULL. En effet l'allocation n'est réellement effectuée qu'à la première utilisation de l'espace alloué.
    Et que renvoie-t-elle si elle échoue ??? Parce que le man, lui, parle explicitement de NULL...

    Citation Envoyé par Neckara Voir le message
    On peut aussi faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #define Malloc(Z) ( alloc_it < alloc_max ? ( alloc[alloc_it++] = malloc(Z) ) : NULL )
    #define debutAlloc(SIZE) unsigned int alloc_it = 0; unsigned int alloc_max ; void * alloc[alloc_max = (SIZE)] = {NULL}
    #define finAlloc()  do{ for(int i= 0; i < XX ; ++i) \
               free(alloc[XX]); \
               while(0)
    Ok, c'est réglé je suis complètement dépassé...
    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]

  14. #34
    Membre émérite
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    852
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 852
    Points : 2 298
    Points
    2 298
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Et que renvoie-t-elle si elle échoue ??? Parce que le man, lui, parle explicitement de NULL...
    Je serais curieux de le savoir moi aussi car pour le coup cette affirmation me parait etrange ou alors je n'ai pas bien tout saisi...

    Citation Envoyé par Sve@r Voir le message
    Ok, c'est réglé je suis complètement dépassé...
    Moi aussi et pourtant je suis encore etudiant... Il va falloir que je me remette un peu a jour...

  15. #35
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Ah j'aime pas quand je lis ce genre de truc car je me sens dépassé et ça m'énerve. Bref en quoi "l'encapsulation" fonctionne avec if(!p) et ne fonctionne pas avec if (p == NULL) ? Et quelle différence entre "pointeur invalide" et "pointeur égal à NULL" ?
    Je parle C++ là.
    p == NULL risque de ne pas marcher car l'opérateur de comparaison et le constructeur peuvent ne pas prendre un pointeur en paramètre (ce qui serait logique, l'utilisateur n'a pas à récupérer l'adresse stockée).

    Après, un pointeur "NULL" sera invalide, mais l'inverse ne sera pas forcément vraie selon l'implémentation.

    malloc ne renvoie-t-elle pas NULL quand elle échoue ???
    If size is 0, then
    malloc() returns either NULL, or a unique pointer value that can later
    be successfully passed to free().
    By default, Linux follows an optimistic memory allocation strategy.
    This means that when malloc() returns non-NULL there is no guarantee
    that the memory really is available.
    Il ne me semble pas que malloc puisse échouer pour une autre raison que :
    - la taille passée en paramètre (autant dire que ça ne devrait jamais planter );
    - un problème d'allocation (plus que rare, sauf en cas de fuite mémoire et vérifier le type de retour ne marchera pas sous Linux);
    Donc on peut se permettre de ne pas tester le code de retour de malloc dans certains programmes.

  16. #36
    Expert éminent sénior
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    Mai 2010
    Messages
    3 214
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : Mai 2010
    Messages : 3 214
    Points : 10 140
    Points
    10 140
    Par défaut
    Je pense que c'est pas le meilleur topic pour débattre if(!p) vs if(p == NULL) , alors pour moi un code doit être explicite et if(!p) ne l'est pas.
    Après évidement que ça marche mais du code moche marche très bien en C
    Le define NULL n'a pas été créer pour faire jolie...

    @Neckara
    Ton code est très moche , et n'est vraiment pas un bon exemple , surtout que meme si c'est possible de mettre a peu prés tout sur le define (même des déclaration et du code) , je ne le conseille pas je rappelle que tu fais ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define debutAlloc(SIZE) unsigned int alloc_it = 0; unsigned int alloc_max ; void * alloc[alloc_max = (SIZE)] = {NULL}
    Un define que tu pourra pas utiliser 2 fois (tu vas pas pouvoir faire 2 fois la déclaration de alloc_it).

    Pour un petit code ça peut déjà limite alors sur du gros code si tu code comme ça , je t'envoie boulet vu que ça obligera au programmeur de regarde chaque fois le define (pas simple a lire deja) pour savoir ce que fait ton code.

    Pour être un peu méchant j'ai impression de voir du code débutant inutilement complexe et peu maintenable.

  17. #37
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par Kannagi Voir le message
    Je pense que c'est pas le meilleur topic pour débattre if(!p) vs if(p == NULL) , alors pour moi un code doit être explicite et if(!p) ne l'est pas.
    Après évidement que ça marche mais du code moche marche très bien en C
    Le define NULL n'a pas été créer pour faire jolie...
    Pour moi, c'est même plus qu'explicite :
    - On teste si le pointeur est valide (bon/ok) ou non (pas bon/false) ;
    Je trouve que c'est plus intuitif.

    Il suffit de connaître un minimum le langage pour savoir que :
    - 0 -> false ;
    - NULL -> false ;

    Et puis pour reprendre ton argument, ce n'est pas pour rien qu'en C++, on a ajouté des surcharges pour pouvoir faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if( file);
    if( ! file );
    Pour moi, NULL sert surtout à éviter de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void * ptr = (void *)0;


    @Neckara
    Ton code est très moche , et n'est vraiment pas un bon exemple , surtout que meme si c'est possible de mettre a peu prés tout sur le define (même des déclaration et du code) , je ne le conseille pas je rappelle que tu fais ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define debutAlloc(SIZE) unsigned int alloc_it = 0; unsigned int alloc_max ; void * alloc[alloc_max = (SIZE)] = {NULL}
    Un define que tu pourra pas utiliser 2 fois (tu vas pas pouvoir faire 2 fois la déclaration de alloc_it).
    Le but d'un tel code est d'être mis en début et en fin de fonction.
    Il n'est donc pas fait pour être présent deux fois dans une fonction, après, c'est une chose à documenter etc.
    Ensuite, je ne donne qu'un exemple, on peut très bien ajouter un deuxième argument pour donner un nom de variable unique et donc passer cette limitation.

    Une bonne solution serait d'utiliser des listes chaînée mais il faudrait allouer les maillons .

    Pour un petit code ça peut déjà limite alors sur du gros code si tu code comme ça , je t'envoie boulet vu que ça obligera au programmeur de regarde chaque fois le define (pas simple a lire deja) pour savoir ce que fait ton code.
    Non, il n'a pas à le savoir.
    Il sait juste qu'il "réserve" X allocations.
    Il fait X allocation puis il "libère" en fin de fonction et c'est tout.
    Il copie/colle en début et en fin de fonction, il utilise Malloc() au lieu de malloc(), j'ai pas plus simple.

    Après, l'avantage des #define, c'est que ce genre de code est censé être utilisé de partout. Il est inconcevable de copier coller plusieurs lignes dans toutes les fonctions. Ceci sera bien plus maintenable que de corriger 5/6 lignes par fichiers .

    Ensuite, ce n'est pas en 5 minutes à 20h après une longue journée de cours que je vais pondre un code "super propre" comme ça sur un coup de tête

    Je ne sais pas si c'est possible de faire ça par contre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #define Malloc ...
     
    #define ManagedFunction(PROTOTYPE, CORPS, ALLOC_MAX) \
    PROTOTYPE \
    { \
               début; \
               CORPS \
               fin; \
    }
    Je pense qu'on pourrait faire des choses marrantes avec

    On pourrait même faire une unique allocation mémoire au début puis on gère soit-même sa mémoire (juste pour s'amuser un peu ).

    EDIT : Oui ça marche \o/
    On va pouvoir s'amuser un peu

  18. #38
    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
    Pourquoi choisir des macros plutôt que des fonctions inline ?

  19. #39
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par Bktero Voir le message
    Pourquoi choisir des macros plutôt que des fonctions inline ?
    Mais euh... s'il faut que je réfléchisse avant de poster aussi
    Le seul "inconvénient" c'est qu'il faudra déclarer soit-même les variables donc oui, je pense que les fonctions inlines seront plus appropriées.

    Pour mon dernier code, le but serait de pouvoir faire un peu comme le Java fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    synchronisez void foo(void)
    {
     
    }
    Donc là les macros seront obligatoires je pense.

  20. #40
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Points : 7 882
    Points
    7 882
    Par défaut
    Citation Envoyé par Neckara Voir le message
    Ensuite, pour le malloc, attention, sous Linux, par défaut, le malloc ne renverra jamais NULL.
    Pas souvent, mais pas jamais. malloc renverra NULL sous linux si l'espace adressable est épuisé, donc pas plus de 4 Go (et même 3 Go en général car le noyau se réserve 1 Go) pour un processus en 32 bit. Pour un processus en 64 bit, la configuration par défaut place aussi une limite "raisonnable" sans plus de détail. Les OS plus conformes aux standards n'autorisent pas de malloc si la mémoire disponible (incluant une partie de la RAM plus la taille cumulées des zones de swap éventuelles) ne permet pas de stocker les pages réservées par la totalité des processus en cours.
    En effet l'allocation n'est réellement effectuée qu'à la première utilisation de l'espace alloué.
    Ce mode de fonctionnement n'est pas spécifique à Linux. Tous les OS modernes qui implémentent la mémoire virtuelle et la pagination à la demande n'allouent de la mémoire réelle (RAM ou swap) qu'au fur et à mesure de l'utilisation de chaque page mémoire utile. Les pages allouées (on devrait dire réservées) mais jamais utilisées n'ont pas de contenu et ne sont donc stockées nulle part.
    ɹǝsn *sıɹɐlos*

Discussions similaires

  1. Comment bien déboguer son code ?
    Par D[r]eadLock dans le forum Débuter
    Réponses: 47
    Dernier message: 02/04/2024, 16h06
  2. [JSmooth] Bien intégrer la JRE avec son programme
    Par Ceubex dans le forum EDI et Outils pour Java
    Réponses: 0
    Dernier message: 30/03/2012, 23h01
  3. [mise en page] pour bien indenter son code
    Par bihorece dans le forum C++Builder
    Réponses: 4
    Dernier message: 06/08/2003, 16h14
  4. Mettre son programme dans Envoyer Vers ?
    Par MaTHieU_ dans le forum C++Builder
    Réponses: 11
    Dernier message: 29/07/2003, 19h09
  5. Réponses: 13
    Dernier message: 11/05/2003, 13h25

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