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 lignesd'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
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é".
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.
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...
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é".
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).
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
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é".
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é".
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
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
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 :/
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
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é".
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.
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
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é".
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.
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
// 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).
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 ?
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é".
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
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é".
Pour ta question fais en une nouvelle pour attirer de nouveau gens
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.
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é".
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
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é".
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
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é".
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é".
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
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é".
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é".
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
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é".
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é".