Moving Ball > Problème de test de sortie d'écran non effectué

Salut,
Pour la gestion de la mémoire je crois que si tu passes une primitive par valeur (une simple nombre, un simple caractère, un booléen, etc, la mémoire est libérée lorsque le programme sort du scope ou elle est utilisée.
par exemple

void use_number(int number) {
    // une opération avec number...
} // <- number sort du scope ici et sa mémoire devrait être libérée

par contre si tu passes une copie d’une structure complexe comme l’instance d’un objet, à ce moment là il y aura une allocation faite sur le heap de la mémoire, et en c/c++ il me semble qu’il faut que tu libère la mémoire manuellement si ton objet est censé avoir une durée de vie limitée dans le code. C’est pour ça qu’à priori pour ce genre de structure il vaut mieux utiliser des pointeurs. Mais si tu as quand même besoin d’un copie il faut que tu utilises une fonction por nettoyer la mémoire. En c++ il me semble que tu peux libérer de la mémoire avec le mot clé delete.

struct SomeStruct {
   // ... fields
};

void use_object_copy(SomeStruct an_object_copy) {
    // Utiliser an_object_copy
} // <- la mémoire de an_object_copy n'est pas libérée ici

SomeStruct my_object = new SomeStruct();

SomeStruct my_object_copy = new SomeStruct();
memcpy(&my_object_copy, &my_object, sizeof(my_object_copy)); // il y a peut-être d'autres manière de faire des copies en c++ mais je ne sais plus trop..

use_object_copy(my_obect_copy);
// Ici la mémoire utilisée par my_object_copy est toujours utilisée, donc si tu sais que tu n'en auras plus besoin dans le programme tu peux libérer la mémoire avec
delete my_object_copy;

Le mot clé delete appelle le destructeur de la structure. Si ta structure contient des champs avec des allocations dynamique du genre my_object.a_field = new float(), il me semble qu’il vaut mieux implémenter ton destructeur toi même:

struct SomeStruct {
    // ...
    SomeStruct() { // constructor
        a_number = new float();
    }
    SomeStruct() { // destructor
        delete a_number;
    }
    float *a_number;
};

Voilà, mes exemples ne sont peut-être pas à recopier non plus en l’état, il doit y avoir des imprécisions, je ne fais pas beaucoup de c/c++… mais sur le principe de la gestion de la mémoire à mon avis tu peux retenir qu’il vaut mieux créer et utiliser des pointeurs pour toutes les valeurs non primitives, sinon tu dois faire la gestion de la mémoire de tes copies manuellement… Et donc pour répondre très concrètement à ta question 1: le fait que la boucle de rendu se rafraîchisse ne nettoie pas la mémoire, si tu fais une copie à chaque frame et qu’elle n’est pas nettoyée, effectivement tu auras une fuite de mémoire.

Bon courage avec ton développement !

Ouhlala…

@Codnpix Merci d’avoir pris la peine d’essayer d’apporter une réponse à @Cric … mais hélas, il y a beaucoup de confusion dans ta réponse, et j’ai peur que @Cric soit un peu perdu avec, d’une part, des éléments qu’il ne maîtrise pas, et d’autre part, des erreurs fondamentales… :confused:

Par ailleurs, je suis désolé, mais je ne peux pas non plus me permettre de passer mon temps à tout détailler dans mes explications, c’est beaucoup trop chronophage, et il existe de nombreuses ressources en ligne pour apprendre le C++. Je vous encourage donc à aller les étudier en préambule, puis à revenir poser des questions plus ciblées qui ne demandent pas à chaque fois de toute reprendre à la base. Sinon c’est diificilement gérable à la longue.

Par exemple, voici une bonne référence : Learn C++

Le passage par valeur (que la variable soit d’un type fondamental ou non) entraîne nécessairement une copie des données (passées en argument) sur la pile (stack). Mais le tas (heap) n’intervient pas du tout dans ce processus. Par conséquent, lorsqu’on souhaite passer un objet (donc une aggrégation de données), instance d’un struct ou d’une class, le passage par valeur est à proscrire. Ceci pour éviter d’encombrer la pile avec une multitude de données liées les unes aux autres, et d’éviter du même coup d’effondrer les performances. Surtout si la fonction ou la méthode est appelée de nombreuses fois (comme dans une boucle par exemple). Enfin, une fois que la fonction ou la méthode est terminée, les données sont retirées de la pile automatiquement. Il n’y’a rien à faire de particulier ici. Il ne s’agit pas d’allocation dynamique (qui, elle, implique le tas) et pour laquelle il faut explicitement veiller à libérer la mémoire allouée.

@Cric je t’ai donné des éléments pour écrire les choses correctement lorsque tu manipules des objets, en utilisant le passage par référence. Je n’ai pas ajouté la notion de pointeur pour ne pas t’embrouiller avant que tu aies digéré le code et ses implications (même si ces notions ne sont pas étrangères l’une à l’autre). Essaie de les appliquer et de relire ce que je t’ai écrit, ou d’aller te renseigner sur le sujet en cherchant par toi-même. Les infos pululent sur le sujet…

Pour ce qui est de scinder ton code en plusieurs fichiers, je te laisse un peu chercher par toi-même également (je t’ai déjà donné l’essentiel des éléments, auxquels tu devras ajouter l’utilisation de la directive #include, que tu utilises déjà par ailleurs). Si vraiment tu ne t’en sors pas, tu peux revenir poser la question. :wink:

On essaye de rester sympa quand même hein :wink:

?.. Qu’est-ce qu’il y a de pas « sympa » ?

Ben c’est un peu condescendant ton “oulalah”… on fait ce qu’on peut …

Bref désolé pour ma confusion, j’aurais peut-être pas dû me lancer dans une explication sachant que j’ai pas touché de c++ depuis un moment. Effectivement la copie est automatique lors du passage par valeur, et donc gérée par le compilateur sur la pile, il y a des languages où c’est pas systématique.

Bonne continuation à tous.

1 Like

Absolument pas ! Et je suis désolé que tu l’aies pris comme ça…

Évidemment qu’on fait ce qu’on peut :slight_smile:
Et moi le premier ! Je ne prétends pas avoir toutes les réponses, loin de là, mais je pense m’être déjà penché sur pas mal de questions pour avoir quelques réponses à apporter tout de même.

Maintenant, si mes interventions vous dérangent, je peux aussi cesser d’intervenir…

Absolument @Steph, j’ai tout ce qu’il me faut dans les échanges que nous avons eus pour avancer mon projet, je te remercie.

Idem, ce sujet, je peux le traiter seul.
Garde ton précieux temps pour avancer sur ton dev Gamebuino :wink:

Concernant la gestion de la mémoire, merci pour vos précisions (Step et @Codnpix), c’était juste pour comprendre.

P.S. j’ai abordé les pointeurs lors de mes cours en C (il y a très longtemps…), donc pas de soucis de compréhension de mon côté. Et j’ai fait assez d’assembleur (Z80, Saturn et autres processeurs Sharp) pendant ma jeunesse pour savoir manipuler les piles :slight_smile:
Et mes calculatrices HP sont mes amies !

Que de souvenirs…

C’est la calculatrice qui m’a accompagnée pendant toutes mes études supérieures… J’ai une ligne qui a disparu de l’affichage depuis quelques années hélas.
J’avais fait l’acquisition d’une carte d’extension de 128 K (800 francs à l’époque !) pour y coller mes anti-sèches programmes pour être à l’aise !

Mais la calculatrice que j’utilise depuis la 3ème (et encore aujourd’hui) est la HP 11C.

J’en ai quelques autres en stock (HP 50G, HP 71B…), c’est vraiment de chouettes machines…

@Cric @Steph
Une question me turlupine…

Pourquoi mettre du code dans des structs ?
Certes, c’est possible en C++, mais c’est pas vraiment l’usage.
La façon “normale” en C++ est d’utiliser des objets.

Pourquoi donc alors ?

1 Like