Partage
  • Partager sur Facebook
  • Partager sur Twitter

fuite de mémoire

Sujet résolu
    28 août 2018 à 16:42:09

    Bonjours a tous,

    je commence une classe réseau mais j'ai trouve une fuite de mémoire au tout debout a la connexion du client .

    Je ne trouve pas le problème .

    struct DATA {
            char* ip;
            int port;
            SOCKADDR_IN csin;
            SOCKET csock;
    };
    
    
    const TCPSocket::DATA TCPSocket::newclient() {
        DATA data;
        socklen_t sinsize = sizeof (data.csin);
        
        if ((data.csock = accept(sock, (SOCKADDR *) & data.csin,& sinsize)) != INVALID_SOCKET) {
            data.ip = inet_ntoa(data.csin.sin_addr);
            data.port = data.csin.sin_port;
            return data;
        } else {
            data.ip = new char[1];
            data.ip[0] = '0';
            return data;
        }
    }

    pour le test j'ai fait un code simple

    int main(int argc, char** argv) {
        
        TCPSocket a;
        
        a.start(123456);
        
        for(;;){
            TCPSocket::DATA data = a.newclient();
            delete data.ip;
            delete data.csin.sin_zero;
        }
    }

    il y a 2 problème 1er il y a une fuite de mémoire et 2 eme il y a un warning 

    main.cpp:22:26: warning: deleting array 'data.TCPSocket::DATA::csin.sockaddr_in::sin_zero'


    merci d’avance pour votre aide .

    • Partager sur Facebook
    • Partager sur Twitter
      28 août 2018 à 18:05:06

      Salut,

      Tu alloue data.ip avec l'opérateur "new[]" et le delete avec delete au lieu de "delete[]"

      Pour l'autre soucis, je ne connais pas SOCKADDR_IN et j'ai pas le temps de chercher maintenant donc à voir plus tard pour ma part ;)

      EDIT : et dans la fonction accept, t'es sûr qu'il faut que tu passes l'adresse de sinsize que tu n'utilises même pas ensuite ? un NULL ne suffirait pas ? (pareil, pas le temps d'aller voir la doc de accept de mon côté)

      -
      Edité par romantik 28 août 2018 à 18:08:56

      • Partager sur Facebook
      • Partager sur Twitter
      Dream on, Dream on, Dream until your dream comes true
        28 août 2018 à 18:31:20

        Il y a plusieurs problemes,

        Déjà, avec inet_ntoa

               The inet_ntoa() function converts the Internet host address  in,  given
               in  network  byte  order,  to a string in IPv4 dotted-decimal notation.
               The string is returned in a statically allocated buffer,  which  subse‐
               quent calls will overwrite.
        


        qui retourne l'adresse d'un tampon statique qui va être reutilisé.  Quand on en fait un delete/free, c'est normal que ça se passe mal.

        Ce qu'il faut stocker dans la structure DATA, ce n'est pas l'adresse de ce tampon, mais une copie de son contenu.

        Une bonne idée, puisque tu écris du C++, serait d'en faire une std::string.

        Ensuite, ça serait peut être bien que l'échec d'accept provoque une exception, puisqu'on en dispose.

        -
        Edité par michelbillaud 28 août 2018 à 18:33:52

        • Partager sur Facebook
        • Partager sur Twitter
          29 août 2018 à 15:07:55

          Une raison pour laquelle tu fais une allocation de char* plutôt que d'utiliser std::string ?
          • Partager sur Facebook
          • Partager sur Twitter

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

            29 août 2018 à 18:28:56

            la "raison" est que sait pour homogénéiser les type de variable qui est dans DATA (bas niveau) .

            existe t-il des lib propre déjà développe sinon je v'ai partir sur QT ?

            • Partager sur Facebook
            • Partager sur Twitter
              29 août 2018 à 19:01:01

              Propre et Qt ensemble ?

              Cf https://en.cppreference.com/w/cpp/links/libs#Communication Les plus connues sont probablement boost.asio et POCO

              • Partager sur Facebook
              • Partager sur Twitter
                30 août 2018 à 13:27:59

                std::string est bas niveau aussi. Tu peux utiliser .data() sur cette dernière qui te donne accès au char*.
                • Partager sur Facebook
                • Partager sur Twitter

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

                  30 août 2018 à 14:07:51

                  Bon, si les donnees contiennent des octets nuls, c'est  vrai que std::string ca va pas le faire.

                  En tout cas, il faut sauver une copie du contenu du tampon, pas son adresse 

                  • Partager sur Facebook
                  • Partager sur Twitter
                    31 août 2018 à 7:49:20

                    merci de votre aide avec une copy il n' a plus de fuite
                    • Partager sur Facebook
                    • Partager sur Twitter
                      31 août 2018 à 10:04:17

                      Bonjour MichelBillaud,

                      pourquoi ça se passe mal si on désalloue une variable statique ? Veux-tu dire qu'il fallaiit désallouer un pointeur statique plutôt ?

                      je cite :

                      qui retourne l'adresse d'un tampon statique qui va être reutilisé.  Quand on en fait un delete/free, c'est normal que ça se passe mal.

                      Merci

                      • Partager sur Facebook
                      • Partager sur Twitter
                        31 août 2018 à 11:15:10

                        YES, man a écrit:

                        Bonjour MichelBillaud,

                        pourquoi ça se passe mal si on désalloue une variable statique ? Veux-tu dire qu'il fallaiit désallouer un pointeur statique plutôt ?

                        je cite :

                        qui retourne l'adresse d'un tampon statique qui va être reutilisé.  Quand on en fait un delete/free, c'est normal que ça se passe mal.

                        Merci

                        Pourquoi ça se passerait bien ?

                        Une variable statique n'a pas été allouée par malloc().

                        Pour résumer, il y a différents classes de variables

                        • variables locales d'une fonction
                        void foo()
                        {
                            int var = 12;
                            ...
                        }
                        

                        Elles font partie du "cadre de pile" qui est crée quand on appelle la fonction. Elle sont donc allouées (dans la plupart des implémentations) dans le segment de pile en entrant et désallouées en sortant automatiquement. Et pour cette raison on parle d'allocation automatique.

                        • les variables globales
                        char version[] = "v3.14";
                        

                        L'espace qu'elles occupent est réservé dès le chargement du programme. Ce sont des variables statiques. Elles habitent dans le segment de données. 

                        • les variables locales déclarées statiques
                        // cette fonction retourne successivement 1, 2, 3, ...
                        
                        int prochain_numero_de_serie()
                        {
                            static int dernier_numero = 0;
                            dernier_numero += 1;
                            return dernier_numero;
                        }
                        


                        ce sont aussi des variables statiques, leur visibilité étant simplement limitée à la fonction où elles sont déclarées. 

                        Enfin, à côté de ça, il y a l'allocation dynamique, qui consiste à allouer/liberer explicitement de l'espace sur le "tas" (heap)". Espace que l'on manipulera par l'intermédiaire d'un pointeur, malloc et free. Mais c'est une autre histoire.

                        Conclusion : la doc te dit que la fonction retourne l'adresse d'un tableau statique, le free() ne va certainement pas marcher sur un truc qui n'a pas été alloué dynamiquement par malloc().

                        -
                        Edité par michelbillaud 31 août 2018 à 11:20:40

                        • Partager sur Facebook
                        • Partager sur Twitter
                          31 août 2018 à 12:14:13

                          @MichelBillaud, merci beaucoup pour tes explications claires
                          • Partager sur Facebook
                          • Partager sur Twitter

                          fuite de mémoire

                          × 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