Partage
  • Partager sur Facebook
  • Partager sur Twitter

Grosses fuites memoires en SDL2

Sujet résolu
    3 juin 2020 à 11:13:51

    Bonjour,

    j'ai déjà vu quelques posts sur ce sujet, mais tous soit se trompent, soit déclarent des mini-pertes... Tandis que moi, avec un code de base, valgrind me renvoie 2000 lignes d'erreurs et m'annonce à la fin:

    ==5367== LEAK SUMMARY:
    ==5367==    definitely lost: 449 bytes in 3 blocks
    ==5367==    indirectly lost: 28,512 bytes in 132 blocks
    ==5367==      possibly lost: 0 bytes in 0 blocks
    ==5367==    still reachable: 149,074 bytes in 802 blocks
    ==5367==         suppressed: 0 bytes in 0 blocks

    Pourtant, je ne vois pas où est-ce que je pourrait avoir fait une erreur, voici le code :

    #include <SDL2/SDL.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    
    int main(int argc, char **argv)
    {	
        // Notre fenêtre
    	
        SDL_Window *fenetre = NULL;
    	
    	
        // Initialisation de la SDL
    	
        if(SDL_Init(SDL_INIT_VIDEO) < 0)
        {
            printf ("Erreur lors de l'initialisation de la SDL : %s", SDL_GetError());
            SDL_Quit();
    		
            return -1;
        }
    	
    	
        // Création de la fenêtre
    	
        fenetre = SDL_CreateWindow("Test SDL 2.0", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN);
    	
        SDL_Delay (1000);	
    
        // On quitte la SDL
    	
        SDL_DestroyWindow(fenetre);
        SDL_Quit();
    	
        return 0;
    }
    

    ... Au départ, je faisait un petit tetris et il grimpait à 80% de la memoire en 15 min... Ce qui est assez désagréable lorsque l'on joue.

    Merci d'avance !

    PS : c'est bien 80% de la mémoire, pas du CPU.

    -
    Edité par Durza42 3 juin 2020 à 11:17:46

    • Partager sur Facebook
    • Partager sur Twitter

    La gentillesse est le langage qu'un sourd peut entendre et qu'un aveugle peut voir.

    Il n'y a qu'un seul monde et il est faux, cruel, contradictoire, séduisant et dépourvu de sens. Un monde ainsi constitué est le monde réel. Nous avons besoin de mensonges pour conquérir cette réalité, cette "vérité".

      3 juin 2020 à 11:47:19

      Salut,

      Pour ton tetris, a mon avis, tu avais d'autres leaks  (si tu crées des surfaces que tu ne désalloues pas à chaque tour de boucle par exemple, erreur classique)

      Sinon, dans ton code, je ne vois pas forcément de leak... Après, est ce que SDL en a de base ? Je ne sais pas. Mais certainement pas 80% de ta mémoire avec ce code la.

      • Partager sur Facebook
      • Partager sur Twitter

      Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

        3 juin 2020 à 16:32:17

        Salut,

        C'est sur, je parlait de mon tetris pour les 80%...

        (si tu crées des surfaces que tu ne désalloues pas à chaque tour de boucle par exemple, erreur classique)

        justement, c'est bien ce que j'avais pensé, mais il n'y a de ça nul part. J'ai sûrement dû mal chercher...

        • Partager sur Facebook
        • Partager sur Twitter

        La gentillesse est le langage qu'un sourd peut entendre et qu'un aveugle peut voir.

        Il n'y a qu'un seul monde et il est faux, cruel, contradictoire, séduisant et dépourvu de sens. Un monde ainsi constitué est le monde réel. Nous avons besoin de mensonges pour conquérir cette réalité, cette "vérité".

          3 juin 2020 à 17:19:08

          Beaucoup de gens pensent que réutiliser le même pointeur préserve des leaks :

          while()
          {
             p = allouer
          
          
          }
          free(p);

          Ce code va t'exploser la mémoire, beaucoup pensent que comme c'est toujours p, alors il n'y a pas de leak.

          Les fonctions SDL comme les chargement d'image, le createRGBSurface, et même TTF_RenderFont  créent des surfaces, qu'il faut donc nettoyer autant de fois qu'on alloue : si on appelle ça dans la boucle, on désalloue dans la boucle (ou on s'arrange autrement).

          • Partager sur Facebook
          • Partager sur Twitter

          Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

            3 juin 2020 à 18:05:04

            Salut,

            Montre-nous le code. Ce sera plus simple de discuter en se basant dessus plutôt qu'en faisant des hypothèses.

            • Partager sur Facebook
            • Partager sur Twitter
            Tutoriel Ruby - Bon tutoriel C - Tutoriel SDL 2 - Python avancé - Faîtes un zeste, devenez des zesteurs
              5 juin 2020 à 18:17:42

              je précise que je n'utilise pas d'alocation dynamique moi-même dans mon code.

              Eh bien... c'est à dire qu'il est un peu long, je vais essayer de vous envoyer quelques morceaux de code type :

              int bouclePrincipale () {
              
                 int continuer = 1, perdu = 0, play = 0, action = 0;
              
                 SDL_Event event;
                 Uint8 *clavier;
                 SDL_Event event2;
                 Uint8 *clavier2;
              
                 while (!perdu) {//tant que l'utilisateur n'a pas perdu
                    continuer = 1;
                    if (preBoucle () == 1) {//on fait tous les réglages et on envoye le bloc suivant. Si ce bloc rencolntre un autre bloc avant d'être descendu, c'est que l'utilisateur a perdu
                       return 0;//donc on quitte cette fonction
                    }
                    
                    while (continuer) {//boucle qui s'effectue tant que le bloc n'est pas arivé en bas
                       action = 0;
                       tmpACT = SDL_GetTicks();
                       if (DERtmp + acc < tmpACT) {//tous les acc (1 seconde au depart, pui accélère à chaque niveau)
                          descendreBloc ();//on descend le bloc
                          DERtmp = tmpACT;//et on ramène le temps pour que le bloc ne se téléporte pas en bas
                          action = 1;//il s'est passé quelque chose, on rafraichit la map
                       } else {}
              
                       if (suivant) {//si c'est au bloc suivant (condition décidé dans la fonction descendreBloc)
                          continuer = 0;//on gère juste les évenements et on sort de cette boucle
                       } else {}
              
                       SDL_WaitEventTimeout(&event, acc);//on atend un event pendant le temps de descente d'un bloc max
                       if ( event.window.event == SDL_WINDOWEVENT_CLOSE ) { // Fermeture de la fenêtre
                          SDL_DestroyWindow(var.fenetreJ);//destruction de l'autre fenetre
                          exit (EXIT_SUCCESS);//on sort du programe
                       } else{}
              
                       switch (event.type) {
                          case SDL_KEYDOWN://appui sur une touche
                             action = 1;
                             if ( event.key.keysym.sym == SDLK_LEFT ) {//touche gauche, on va à gauche
                                allerAGauche ();
                             }
                             else if (event.key.keysym.sym == SDLK_RIGHT) {//touche droite, on va à droite
                                allerADroite ();
                             }
                             else if (event.key.keysym.sym == SDLK_END) {//touche fin, on tourne dan le sens horaire
                                tourner ();
                             }
                             else if (event.key.keysym.sym == SDLK_UP) {//touche haut, on va tourne dans le sens anti-horaire
                                tournerGauche ();
                             }
                             else if (event.key.keysym.sym == SDLK_DOWN) {//touche droite, on accélère la descente
                                allerEnBas ();
                             }
                         break;
                          default:
                         break;
                       }
                       if (action == 1) {//si il s'est passé quelque chose, on recharge la map
                          chargerMap ();
                          SDL_RenderCopy (var.rendererJ, var.separator, NULL, &var.Rsep);
                          SDL_RenderPresent (var.rendererJ);
                       }
                    }
                 }
                 return 0;
              }
              

              C'est la fonction la plus longue du code, où je gère tous les events.

              ChargerMap :

              void chargerMap () {
                 for (i = 0 ; i < 400/25 ; i++) {//on parcourt la matrice en x
                    for (j = 0 ; j < 550/25 ; j++) {//on parcourt la matrice en y
                       if (Tmap [i][j] != NULL) {//si le bloc [i][j] existe
                          SDL_RenderCopy (var.rendererJ, Tmap [i][j], NULL, &map [i][j]);//on l'affiche
                       } else {}
                    }
                 }
                 compteur ();//affiche le score
              }
              

              Si vous en voulez d'autre dites le moi, je ne veux juste pas surcharger le sujet.

              merci !

              ----- edit -----

              la structure des variables :

              typedef struct {//structure de 4 carré (tétrominos)
                 SDL_Texture *b1, *b2, *b3, *b4;
                 SDL_Rect r1, r2, r3, r4;
              } Blocs;
              
              typedef struct {//ensemble de mes variables
                 SDL_Window *fenetreJ, *fenetre2J;
                 SDL_Renderer *rendererJ, *renderer2J;
                 Blocs bloc;
                 SDL_Texture *separator;//pour faire joli, séparer le jeu lui même du compteur.
                 SDL_Rect Rsep;
              } Variables;
              



              -
              Edité par Durza42 6 juin 2020 à 10:21:46

              • Partager sur Facebook
              • Partager sur Twitter

              La gentillesse est le langage qu'un sourd peut entendre et qu'un aveugle peut voir.

              Il n'y a qu'un seul monde et il est faux, cruel, contradictoire, séduisant et dépourvu de sens. Un monde ainsi constitué est le monde réel. Nous avons besoin de mensonges pour conquérir cette réalité, cette "vérité".

                22 juin 2020 à 17:35:44

                up svp...

                • Partager sur Facebook
                • Partager sur Twitter

                La gentillesse est le langage qu'un sourd peut entendre et qu'un aveugle peut voir.

                Il n'y a qu'un seul monde et il est faux, cruel, contradictoire, séduisant et dépourvu de sens. Un monde ainsi constitué est le monde réel. Nous avons besoin de mensonges pour conquérir cette réalité, cette "vérité".

                  22 juin 2020 à 20:01:02

                  Hello,

                  En deux semaines, tu n'as pas réussi à trouver ton souci ? Tu as mal cherché, et si tu penses que ça vient de sdl, détrompe-toi.

                  Poster des fragments de code, ce n'est pas représentatif du code qui s'exécute. Mais n'espère pas que si tu postes 500 lignes de code, quelqu'un va se mettre à les analyser pour trouver d'où vient la perte de mémoire.

                  Il y a un machin qui s'appelle debugger pour t'aider à trouver d'où vient le problème.

                  Et il y a aussi une méthode de programmation: on écrit quelques lignes de code, on teste, on en ajoute, on re-teste, etc....

                  -
                  Edité par edgarjacobs 22 juin 2020 à 20:01:30

                  • Partager sur Facebook
                  • Partager sur Twitter

                  On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

                  Anonyme
                    22 juin 2020 à 20:55:03

                    salut,

                    Déjà les booléens c'est bien ! (#stdbool.h) et ensuite quel est l'utilité d'un "else{}" dans ton code ? (lignes 23, 27, 33).

                    Actuellement je vois clairement un problème du type cité plus haut mais on peut rien faire car aucune apparition de la structure Blocs ni même un SDL_createTextureFromSurface ou ses cousins :/

                    Je te conseil quand tu commences à faire de la SDL à réfléchir l'utilisation de tes textures tel un musée. Pour faire simple dans un musée on a :

                    - des étudiants en art qui viennent regarder les œuvres exposées et prendre leur nom

                    - un conservateur qui gère le musée

                    - ET DES PANNEAUX "PAS TOUCHE !" PARTOUT !

                    Au lieu de créer un texture pour chaque bloc de ton tétromino pourquoi pas la copier ? Surtout pour un même bloc où c'est 4 fois le même bloc donc ça ne sert à rien de les avoir en doublons (surtout que ça tape dans de le disque comme un con). Et puis tous les tétrominos possèdent des textures communes, alors pourquoi ne pas les regrouper ?

                    C'est là que le musée arrive ! Il te suffit de créer une variable structuré ou un tableau indexé par une énumération et de stocker toutes les textures des blocs dedans, c'est donc ton musée. Le conservateur sera les fonctions qui permettront de modifié ce tableau et accédé à des éléments. Enfin tes "Blocs" seront les étudiants. Pour ce qui est des panneaux "pas touche" on fait confiance au mec qui va coder car le C ne permet pas d'avoir de la protection avec les pointeurs (contrairement au C++) et on a pas d'autre choix :/

                    j'espère t'avoir aider ou filer un piste ^^

                    -
                    Edité par Anonyme 22 juin 2020 à 21:02:24

                    • Partager sur Facebook
                    • Partager sur Twitter
                      23 juin 2020 à 10:57:50

                      Je ne pas avoir tout compris à ton histoire de musé, mais pour l'affaire des variables structurées, c'était déjà fait :

                      typedef struct {
                         SDL_Texture *b1;
                         SDL_Rect r1, r2, r3, r4;
                      } Blocs;
                      

                      Par contre, j'avais bien 4 textures... et effectivement, maintenant j'ai l'impression d'avoir un peu de fuites de mémoires, d'autant que je ne libérait effectivement pas les textures avant de les désallouer (je croyait que les textures avait une certaine "adresse" et que les réallouer revenait à écraser le contenu de cette adresse, donc de cette texture, mais non... j'avais mal compris le message de Fvirtman, je croyait qu'il voulait dire redéclarer.).

                      Cependant, ce n'est pas encore parfait, et j'ai remarqué (en écrivant quelques lignes de code, en testant, en en ajoutant, en re-testant, etc ^^ ) qu'en augmentant le nombre d'appels à SDL_RenderPresent j'augmentait les leaks. est-ce que je l'utilise mal ?

                      Et si oui, comment bien l'utiliser (ou une autre fonction serait-elle plus apropriée)?

                      Merci encore.

                      -
                      Edité par Durza42 23 juin 2020 à 11:00:25

                      • Partager sur Facebook
                      • Partager sur Twitter

                      La gentillesse est le langage qu'un sourd peut entendre et qu'un aveugle peut voir.

                      Il n'y a qu'un seul monde et il est faux, cruel, contradictoire, séduisant et dépourvu de sens. Un monde ainsi constitué est le monde réel. Nous avons besoin de mensonges pour conquérir cette réalité, cette "vérité".

                      Anonyme
                        23 juin 2020 à 12:08:34

                        Voici un code pour te montrer un peu le principe du musée :

                        /*--- HEADER ---*/
                        typedef struct {
                           SDL_Texture *img;
                           // le reste de tes données
                        }bloc_s;
                        
                        typedef enum {
                           BLOC_ROUGE = 0,
                           BLOC_VERT,
                           BLOC_BLEU
                           // ...
                        }index_bloc_e;
                        
                        #define SIZE_MUSEUM   16   // taille de ton musée, à toi de voir
                        
                        /*--- SOURCE ---*/
                        
                        // var global mais privé / propre au module
                        static SDL_Texture *museum[SIZE_MUSEUM] = {0}; // init à NULL de tous les pointeurs
                        
                        void MUSEUM_init(SDL_Render *render){
                          // init sera tous les chargments des textures
                          for(int i=0; i < SIZE_MUSEUM; i++){
                             // load : bloc_s.img = image charger; // cette ligne peut être faite via le get_texture, à toi de voir
                         } } SDL_Texture* MUSEUM_get_texture(index_bloc_e couleur){ return museum[couleur]; // on ne vérifie pas pour faire volontairement planté le programme en cas d'erreur car cela signifia un mauvaise manipulation du musée } void MUSEM_destroy(void){ // décharge toutes les textures for(int i=0; i < SIZE_MUSEM; i++){ if(museum[i] != NULL){ SDL_DestroyTexture(museum[i]); } } }


                        Tu peux aussi, et je te le conseil, utiliser un structure pour regrouper plus d'infos comme la taille du musée (donc le nombre de case à lire dans le tableau) et ainsi avoir quelque chose d'un peu plus flexible. Il y a plein d'amélioration à faire, ce n'est qu'un début

                        Le plus important à comprendre c'est le bloc_s.img = image à charger; c'est ce qui fait la particularité et l'efficacité du musée ! Au lieu de charger une nouvelle image à chaque fois on passe au bloc un pointeur sur une image, il porte donc sur lui le nom, un photo pourquoi pas, du tableau qu'il va présenter devant tout le monde mais en aucun cas il le prend avec lui, le tableau est rester dans le musée.

                        -
                        Edité par Anonyme 23 juin 2020 à 12:12:20

                        • Partager sur Facebook
                        • Partager sur Twitter
                          24 juin 2020 à 19:07:49

                          OK, effectivement ça a l'air puissant... Encore une preuve de la masse infinie de choses à apprendre.

                          Je n'avais jamais pensé non plus à stocker en mémoire les images dont j'avais si souvent besoin, ça va beaucoup plus vite !

                          Pour donner un ordre de grandeur, j'ai environ mille fois moins de pertes de mémoires (littéralement), en plus de simplifier le code !

                          -
                          Edité par Durza42 29 juin 2020 à 15:12:59

                          • Partager sur Facebook
                          • Partager sur Twitter

                          La gentillesse est le langage qu'un sourd peut entendre et qu'un aveugle peut voir.

                          Il n'y a qu'un seul monde et il est faux, cruel, contradictoire, séduisant et dépourvu de sens. Un monde ainsi constitué est le monde réel. Nous avons besoin de mensonges pour conquérir cette réalité, cette "vérité".

                            24 juin 2020 à 19:49:28

                            BrigitteLPB a écrit:

                            SDL_Texture* MUSEUM_get_texture(index_bloc_e couleur){
                               return museum[couleur]; 
                               // on ne vérifie pas pour faire volontairement planté le programme en cas d'erreur car cela signifia un mauvaise manipulation du musée
                            }
                            
                            // on ne vérifie pas pour faire volontairement planté le programme en cas d'erreur car cela signifia un mauvaise manipulation du musée
                            Super cette technique de programmation.

                            • Partager sur Facebook
                            • Partager sur Twitter

                            On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

                            Anonyme
                              24 juin 2020 à 21:45:48

                              edgarjacobs a écrit:

                              // on ne vérifie pas pour faire volontairement planté le programme en cas d'erreur car cela signifia un mauvaise manipulation du musée

                                 Super cette technique de programmation.

                              Il est vrai qu'on pourrait vérifier et renvoyer un pointeur NULL mais là on index avec une énumération donc on sait à l'avance tout ce qu'il y aura dedans ! Donc si couleur fait tout planter alors cela signifie qu'il y a un problème de codage dans le module quelque part (tableau trop petit par exemple) et ça ne sert à rien d'aller plus loin, on a rencontré un problème majeur car cette case est supposé existante. Dans le cas d'un indexage avec des nombres il faut vérifier car l'utilisateur peut  tout envoyer comme index, contrairement à une énumération qui a des valeurs prédéfinis donc il est impossible d'envoyer des mauvais index. Voilà pourquoi je préfère rentrer dans l'erreur, une façon de corriger cela et d'avoir quelque chose de plus flexible serait d'abuser des structures et pourquoi pas une pile de texture (attention plus long en accès).

                              • Partager sur Facebook
                              • Partager sur Twitter
                                27 juin 2020 à 11:00:24

                                j'aurais simplement une dernière petite question : comment rafraichir intelligement l'écran ? Parce que si un seul pixel s'est déplacé, ce serait bête de rafraichir tout l'écran, non ?

                                • Partager sur Facebook
                                • Partager sur Twitter

                                La gentillesse est le langage qu'un sourd peut entendre et qu'un aveugle peut voir.

                                Il n'y a qu'un seul monde et il est faux, cruel, contradictoire, séduisant et dépourvu de sens. Un monde ainsi constitué est le monde réel. Nous avons besoin de mensonges pour conquérir cette réalité, cette "vérité".

                                Anonyme
                                  27 juin 2020 à 12:59:18

                                  Durza 42 a écrit:

                                  j'aurais simplement une dernière petite question : comment rafraichir intelligement l'écran ? Parce que si un seul pixel s'est déplacé, ce serait bête de rafraichir tout l'écran, non ?

                                  Généralement moi je réaffiche toutes mes textures à chaque fois mais si tu veux réduire la charge il faudrait créer des textures tampon (ou render jsp, j'ai jamais coder çà) et associer certaines parties de l'image final (ex: background, joueur, décor, ...) et de modifier directement dans une texture précise sans toucher au reste.

                                  Par exemple on change la couleur du joueur alors on va recréer le tampon du joueur mais pas le reste puis on le blit avec le reste (inchangé)

                                  Après je ne sais pas si c'est réellement utile car certes on économise un peu de blit en réduisant le nombre de textures à afficher mais ça complique vachement tout le code, notamment pour la détection de mise à jour

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    27 juin 2020 à 18:04:12

                                    très bien, donc je marque le sujet résolu !
                                    • Partager sur Facebook
                                    • Partager sur Twitter

                                    La gentillesse est le langage qu'un sourd peut entendre et qu'un aveugle peut voir.

                                    Il n'y a qu'un seul monde et il est faux, cruel, contradictoire, séduisant et dépourvu de sens. Un monde ainsi constitué est le monde réel. Nous avons besoin de mensonges pour conquérir cette réalité, cette "vérité".

                                    Anonyme
                                      27 juin 2020 à 19:23:45

                                      Durza 42 a écrit:

                                      très bien, donc je marque le sujet résolu !


                                      Pour ta question fais en une nouvelle pour attirer de nouveau gens ;)

                                      • Partager sur Facebook
                                      • Partager sur Twitter

                                      Grosses fuites memoires en SDL2

                                      × 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