C'est quoi ces pointeurs tout moisi ? Les références ca sert à quelque chose !
Et tu as imbriqué la definition du constructeur de la classe Armature dans celui de la classe Lieu, ce n'est pas comme cela que ça fonctionne, je te conseille de revoir tes bases.
Enfin, SDL est un bibliothèque C, qui pour être utilisée correctement en C++ aurait besoin d'être encapsulée dans un wrapper. Utilises plutôt SFML qui est une bibliothèque C++.
C'est quoi ces pointeurs tout moisi ? Les références ca sert à quelque chose !
Et tu as imbriqué la definition du constructeur de la classe Armature dans celui de la classe Lieu, ce n'est pas comme cela que ça fonctionne, je te conseille de revoir tes bases.
Enfin, SDL est un bibliothèque C, qui pour être utilisée correctement en C++ aurait besoin d'être encapsulée dans un wrapper. Utilises plutôt SFML qui est une bibliothèque C++.
j'avoue que mon pointeur à une sale gueule c'est surement de la le problème ,mais y'a une différence entre SFML et SDL ? d'un point de vue possibilité ?Et c'est quoi un wrapper ?
SDL est comme l'a dit @Deedolith une lib C, donc qui fonctionne avec les pointeurs nus, car il n'y avait que ça en C (à ne pas utilise en C++, les smart pointers sont là).
SFML est au contraire une lib C++ qui utilise les mécanismes apportés par C++ (RAII et orienté objet), qui sont plus adaptées que ces pointeurs sales.
Je ne les connais pas particulièrement, mais elles peuvent sûrement faire plus ou moins le même boulot, c'est juste que SFML est écrite en C++ et est plus pratique à utiliser en C++ (et elle ne te conduit pas à utiliser des pointeurs nus).
Un wrapper est une "interface entre deux langages", un wrapper C++ d'une lib C fera par exemple ceci :
// lib C, comme SDL
void function(const char* msg) {
printf("%s", msg);
}
// lib C++, comme SFML
void function(const std::string& msg) {
function(msg.c_str());
}
// ou en C++17
void function(std::string_view msg) {
function(msg.data);
}
Et ça permet de coder proprement en C++ pendant que le wrapper fait le sale boulot de conversion qui t'évite de polluer ton propre code.
Par exemple, un wrapper C++ de SDL ne t'obligera pas à passer des pointeurs nus, mais des unique_ptr bien RAII et propres au C++.
Faudrait arrêter avec « si tu fais du C++ utilise SFML ». SDL est une bibliothèque C réputée et supportée par des professionnels ainsi que certaines entreprises. SFML est faite par quelques développeurs dont quelques uns sont très peu coopératif, pour ne citer qu'un exemple : le support de wayland a été refusé pendant un long moment jusqu'à ce que Laurent se daigne enfin comprendre (il ne connait rien à Linux mais se permet de refuser une fonctionnalité) qu'il est nécessaire de le rajouter.
Il y a beaucoup de développeurs de projets en C++ qui continuent d'utiliser des bibliothèques C, parfois par stabilité, parfois par fonctionnalités et parfois par choix. En ce qui concerne SDL et SFML, les plateformes supportées sont bien différentes.
- Edité par markand 13 avril 2021 à 9:07:08
git is great because Linus did it, mercurial is better because he didn't.
Sympa la fonction initMap qui prend un pointeur nu de vector de pointeurs nus de Lieu. Parfait pour avoir des problèmes
Je t'avoue que je ne sais pas d'où vient ton pb, mais on peut questionner l'intérêt de charger 1000 fois le même fichier.
C'est juste que je créer des cases dans lesquels mes personnages seront dedans , chaque case est indépendante des autres donc j'initie plusieurs case en fonction de la taille du terrain.
Après , je suis débutant en c++ et j'ai pas l'habitude d'utilisé les références ou les pointeurs intelligents .Bon je vais déjà faire un pointeur propre et on verra si ça bug encore .
markand a écrit:
Faudrait arrêter avec « si tu fais du C++ utilise SFML ». SDL est une bibliothèque C réputée et supportée par des professionnels ainsi que certaines entreprises. SFML est faite par quelques développeurs dont quelques uns sont très peu coopératif, pour ne citer qu'un exemple : le support de wayland a été refusé pendant un long moment jusqu'à ce que Laurent se daigne enfin comprendre (il ne connait rien à Linux mais se permet de refuser une fonctionnalité) qu'il est nécessaire de le rajouter.
Il y a beaucoup de développeurs de projets en C++ qui continuent d'utiliser des bibliothèques C, parfois par stabilité, parfois par fonctionnalités et parfois par choix. En ce qui concerne SDL et SFML, les plateformes supportées sont bien différentes.
Comme je l'ai dit SDL a certains avantages, étant quelque fois contributeur mon avis est biaisé.
Honnêtement il y a pas grand chose à wrapper. Il suffit simplement d'utiliser des std::unique_ptr avec un deleter pour détruire l'objet et le tour est joué.
Exemple avec un SDL_Window et SDL_Renderer qui s'auto détruisent. La seule chose à prendre en compte est la nécessité d'appeler .get() à chaque fois que tu passeras un des objets à une fonctions SDL.
Si tu as déjà touché à SDL, tu peux continuer à l'utiliser, il n'y a pas de soucis et fais comme @markand.
Après, c'est plus une question de goût qu'autre chose car ces libs offrent sensiblement les mêmes fonctionnalités (globalement).
Perso, les rares fois où je fais un peu de graphique, j'utilise SFML, mais c'est mon avis et tu es complètement libre de te faire le tien.
Je suis étonné que personne n'ait encore cité Qt, qui est carrément un framework (pour comparer, SFML propose les bases, genre des formes, et Qt fournit des widgets comme une case à cocher etc.., ça me rappelle que j'en avais codé quelques uns avec SFML ici).
Bref, toutes les 3 se valent, à toi de voir avec laquelle tu te sens plus à l'aise.
Pour en revenir au message initial, 700 fois puis ça bug, ça sent la fuite mémoire.
Regarde en même temps que ton jeu tourne l'évolution de ta courbe de mémoire processus (sous windows dans le gestionnaire de tâches), si tu vois que ça monte, ça monte, ça monte, alors ceci explique cela.
N'oublie jamais que créer une texture, même depuis le même pointeur, provoque un memory leak
pointeur* p;
while(...)
{
p = alloc
// liberer p
}
Typiquement, dans ce cas on réutitlise p pour réallouer à chaque tour de boucle, il ne faut pas croire que ce sur quoi pointait l'ancien p est libéré. Pour ne pas avoir de fuite, on libere aussi dans la boucle.
une alloc = un free.
Concrètement sous SDL, SDL_createRGBSurface alloue : il faut libérer avec SDL_FreeSurface.
Comme je l'ai dit SDL a certains avantages, étant quelque fois contributeur mon avis est biaisé.
Honnêtement il y a pas grand chose à wrapper. Il suffit simplement d'utiliser des std::unique_ptr avec un deleter pour détruire l'objet et le tour est joué.
Exemple avec un SDL_Window et SDL_Renderer qui s'auto détruisent. La seule chose à prendre en compte est la nécessité d'appeler .get() à chaque fois que tu passeras un des objets à une fonctions SDL.
Et évidemment tu peux faire ça avec tout. SDL_Texture, SDL_Surface. C'est une utilisation pratique du unique_ptr.
- Edité par markand hier à 16:14
Je lis et relis ton code et je ne comprend toujours pas l'utilisation du pointeur , le using et la "class" w et r .Si tu pouvais le l'expliquer s'il te plait.
Et en le copiant pour mon attribue window , ça me met un erreur dans mon constructeur comme quoi on n'a pas operator= entre un unique_ptr et un SDL_Window*
Je lis et relis ton code et je ne comprend toujours pas l'utilisation du pointeur , le using et la "class" w et r .Si tu pouvais le l'expliquer s'il te plait.
Et en le copiant pour mon attribue window , ça me met un erreur dans mon constructeur comme quoi on n'a pas operator= entre un unique_ptr et un SDL_Window*
Si tu ne comprends pas c'est que tu dois suivre un cours de C++. Ce sont de simples syntaxes du C++11 (sorti il y a 10 ans).
Pour faire court :
using c'est le typedef en mieux (possibilité de le mettre sous template)
le unique_ptr c'est un smart pointer
tu ne peux pas copier (il faut le déplacer) un unique_ptr, tu peux le prendre en paramètre mais il faut le déplacer avec std::move
git is great because Linus did it, mercurial is better because he didn't.
Je lis et relis ton code et je ne comprend toujours pas l'utilisation du pointeur , le using et la "class" w et r .Si tu pouvais le l'expliquer s'il te plait.
Et en le copiant pour mon attribue window , ça me met un erreur dans mon constructeur comme quoi on n'a pas operator= entre un unique_ptr et un SDL_Window*
Si tu ne comprends pas c'est que tu dois suivre un cours de C++. Ce sont de simples syntaxes du C++11 (sorti il y a 10 ans).
Pour faire court :
using c'est le typedef en mieux (possibilité de le mettre sous template)
le unique_ptr c'est un smart pointer
tu ne peux pas copier (il faut le déplacer) un unique_ptr, tu peux le prendre en paramètre mais il faut le déplacer avec std::move
C'est bon je suis un peu plus à jour sur les template et les pointeurs ,problème c'est l'encapsulation de mes attributs en unique pointeurs ,en gros ça donne ça
Il te faut dans ta classe définir des opérateurs de mouvement : constructeur de mouvement et assignation de mouvement. Par exemple dans plusieurs de mes projets utilisant la SDL2 , j'ai cette classe ci-dessous ( j'ai pas collé tout le fichier ):
Attention avec les pointeurs intelligents, leur bonne utilisation implique de ne pas non plus faire n'importe quoi!
Le point essentiel est le concept de responsabilité. Sur la fonction que tu proposes, il semble évident (au vu du code que tu donnes) que c'est la classe Fenetre qui détient la responsabilté du SDL_Renderer (est ce une bonne idée ou pas, j'ai trop peu d'éléments pour me faire un jugement), l'idée c'est que comme son nom l'indique un unique_ptr, traduit une responsabilité unique, ce qui implique, dans le cas de ta fonction, que la responsabilité du SDL_Renderer va être transférée à l'appelant, qui va le détruire dès qu'il n'en aura plus besoin, et ce faisant va violer une règle centrale de la POO qui veut qu'un objet soit par construction maintenu dans un état cohérent de sa construction jusqu'à sa destruction, à l'issue du return m_renderer est un pointeur NULL.
Plusieurs possibilités sur ce type de cas,
un couple weak/shared, le membre de la classe est un shared et la fonction renvoie un weak, c'est assez lourd, mais je pense que ça peut le faire en design, les weak_ptr n'est pas utilisable même, mais il permet de construire un shared_ptr. L'avantage, du truc, c'est que tant qu'il y a un shared_ptr valide, il n'y a pas de libération, je suis potentiellement assuré que m_renderer ne sera pas libéré ailleurs que dans le destructeur de Fenetre. L'inconvénient du bazar, c'est que le couple weak/smatr implique pas mal de boulot, un weak_ptr ne peut pas être utilisé directement aux donnés pointées pour accéder au données, il faut construire un shared, c'est une mécanique assez lourde, et peut être pas justifiée
class Fenetre
{
std::shared_ptr<SDL_Renderer,SDLWRAP> m_renderer;
std::weak_ptr<SDL_Renderer,SDLWRAP> getRenderer(){return m_renderer;}
};
Une autre solution probablement moins onéreuse, est de renvoyer une référence ou éventuellement un pointeur nu. Le problème majeur du pointeur nu, c'est qu'on va être tenté de le détruire alors qu'il n'est pas sous notre responsabilité.
class Fenetre
{
std::unique_ptr<SDL_Renderer,SDLWRAP> m_renderer;
SDL_Renderer * getRenderer(){return m_renderer.get();}
};
Là je suis un peu plus tranquille, sauf que si je tombe sur quelqu'un comme moi, qui en bon ayatollah de la gestion mémoire risque de se dire que si je ramasse un pointeur, j'en ai la charge...
La solution qui pourrait être la bonne serait de renvoyer soit un pointeur const, soit une référence. Dans les faits c'est plus ou moins une option d'écriture, avec un pointeur const (ou une référence, c'est pareil au niveau du code généré), j'indique clairement à l'appelant que ma class Fenetre conserve la responsabilité du SDL_Renderer. Du coup, je partirai sur un truc du genre:
class Fenetre
{
std::unique_ptr<SDL_Renderer,SDLWRAP> m_renderer;
SDL_Renderer & getRenderer(){return *m_renderer.get();}
};
Sur du C++ pur jus, j'opterai pour une référence, mais la SDL étant une bibliothèque C à la base, je serais sans doute plus tenté par un pointeur const, qui correspondra sans doute mieux au style du reste du code
Si Fenetre à la responsabilité du pointeur ,ca veux dire que c'est la seul qui à accès à mon pointeur et qui peux le détruire ou que c'est elle qui peux le détruire et donc je peux l'utilisé en paramètre.En gros, j'ai juste besoin de renderer pour initié mes textures pour l'instant donc ca m'arrangerais de n'avoir que ma Fenetre qui puisse le supprimer en faite .Quoi qu'il en soit faut que je wrappe mes pointeurs au cas où.
Attention, même si pointeur et référence se ressemblent, il y a quand même des différences.
Déjà, les références sont introduites en C++ donc inexistantes en C, d'où la remarque d'@int21h ( dont je viens de comprendre le pseudo en expérimentant le langage d'assemblage ).
Les références se déclarent comme ceci :
type& typeRef { &typeVar };
// intialisé avec l'adresse d'une variable, donc contrat de validité de l'adresse
// on ne peut pas modifier la valeur d'une référence (càd l'adresse que l'on lui donne)**
Ce ne sont pas des objets, mais plutôt des alias (comme typedef ou using, mais pour les variables), donc pour les utiliser dans des conteneurs on utilise std::reference_wrapper (qui manipule un pointeur en interne).
Le plus important est que l'adresse auquel correspond une référence est valide, contrairement à C avec ses problèmes de pointeurs, aka segfault (on accède à une adresse qui ne nous appartient pas et là boum) ou dangling pointer (pointeur invalide qui pointe vers n'importe quoi et là UB).
Ensuite, les pointeurs : ils sont là depuis C (et même dans un (des ?) langage(s) avant lui), mais en soi ce n'est pas forcément une mauvaise chose.
Le pointeur pointe (sans blague ) sur une adresse, cependant, aucun contrat n'est assuré, le pointeur est soit valide (adresse autorisée et accessible => adresse d'une variable par exemple), invalide (adresse d'une variable supprimée, NULL/nullptr), ou n'importe quoi (non initialisé).
Bref, les références ont été apportées pour éviter au développeur de gérer tout ce qui pourrait mal tourner.
Un exemple de code :
// C++
void increment(int& var) {
var++; // et c'est tout
}
// C
// solution 1 : erreur
void increment(int* var) {
if (!var) {
perror("Pointeur foireux !"); // je crois que c'est ça, mais je ne fais pas de C
}
// pointeur safe
(*var)++;
}
// solution 2 : code de retour
int increment(int* var) {
if (!var) {
return -1;
}
(*var)++;
return 0;
}
int main(void) {
int* val = malloc(sizeof(int));
if (val == NULL) { // alloc échouée
perror(...);
}
*val = 4;
increment(val); // ou on teste avec un if si on utilise la 2e version
}
Bon, la partie C est sûrement améliorable (je n'en fais pas), mais tu as compris la différence.
(Cet article s'éloigne un peu du sujet, mais il illustre plutôt bien la différence entre C et C++)
Il existe aussi les pointeurs intelligents (smart pointers en anglais) apportés pas le C++11 (repris de Boost, je crois ?).
Ces classes gèrent elles-mêmes l'allocation et la libération des ressources, ce qui évite presque tous les problèmes cités ci-dessus (et récurrents avec C), c'est donc pour cela qu'il sont extrêmement recommandés.
** en fait, ce code est parfaitement légal en C++ :
int a{ 10 };
int& ref{ a };
int b{ 100 };
ref = b;
b++;
std::cout << a << ", " << b;
ref = b a juste modifié le contenu de l'alias (donc a) en lui assignant la valeur de b (100).
Je me demande ,il existe pas des wrapper "officiel" ou du moins bien fait car vu mon niveau actuel en C++ il y a de très forte chance que je me plante sur quelque chose en le faisant
Après quelques recherches, il n'y a pas vraiment l'air d'y avoir de wrapper officiel, mais plutôt une multitude de projets amateurs (pas forcément mauvais, github contient de belles choses).
Comme l'ont dit @markand et @Warren79, il n'y a pas grand chose à wrapper, seulement (en gros) virer les pointeurs nus en utilisant des unique_ptr avec un custom deleter (vu qu'un type de SDL est supprimé avec une fonction de SDL) et en mettant des références (constantes si besoin) en paramètre (et pour faire joli, un namespace).
Tu peux t'inspirer d'exemples en cherchant un peu, ce n'est pas très difficile (d'autant plus que ce job n'est pas de recoder SDL mais de créer une interface élégante en C++ pour utiliser des fonctions C qu'on qualifierait de moche en C++).
J'ai une autre question :c'est quoi le mieux pour créer plusieurs objet ?(en soit je veux crée bcp de fois la même classe avec juste les coordonnés qui change mais le reste est le même
-initié 1 instance et la copié dans les autres
-initié toutes les instances
IMG Load bug
× 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.
Liens utiles pour le C++
git is great because Linus did it, mercurial is better because he didn't.
git is great because Linus did it, mercurial is better because he didn't.
Liens utiles pour le C++
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
git is great because Linus did it, mercurial is better because he didn't.
Mon site web de jeux SDL2 entre autres : https://www.ant01.fr
Liens utiles pour le C++
Liens utiles pour le C++