> Tous les forumsAutres langages

 [c++] surcharge new, new[], delete et delete[]Sujet résolu
Statut du sujet : RESOLU Imprimer
 koala01
  Posté le 23/05/2006 @ 13:23  
 Astucien

4715 Messages
Salut, J'essaye déseperément de créer un gestionnaire de mémoire pour le débuggage d'application… Son but est simplement de garder une trace des allocations de mémoire et de leur libération. Pour ce faire, je crée une classe, transformée en singleton pour l'occasion, dont le membre principal est une map prenant en clé les pointeurs alloués et en valeur une structure reprenant les informations utiles sur le pointeur (entre autre, la taille et le fait que ce soit un tableau ou non)… Cette classe contient trois méthodes puliques, dont voici les codes, en vous faisant grâce des détails insignifiants pour résoudre mon problème… bien qu'abondemment commenté pour vous permettre de comprendre le but du code…: -GetInstance(void) qui permet de récupérer l'instance du singleton [code] CManagerMemoire & CManagerMemoire::GetInstance() { static CManagerMemoire InstanceManager; return InstanceManager; }[/code] -Alloue(size_t, booléen) qui permet d'allouer un pointeur et de l'inclure dans la map [code]void * CManagerMemoire::Alloue(std::size_t taille, bool tableau) { //création d'un nouveau bloc à insérer dans la map Bloc nouveau; nouveau.Taille=taille; nouveau.Tableau=tableau; try { //déclaration et allocation du nouveau pointeur void *ptr; if((ptr=malloc(taille))==NULL) //qui jette une exception si elle échoue throw std::bad_alloc(); //insertion du bloc dans la map avec le pointeur en clé Allocations[ptr]=nouveau; //un affichage de base de la réussite std::cout<<"allocation de "<<taille<<" octets pour "<<ptr<<std::endl; return ptr; } catch(...) { //new doit jeter l'exception bad_alloc() s'il échoue std::cout<<"erreur d'allocation"<<std::endl; system("PAUSE"); throw std::bad_alloc(); } }[/code] et -Libere(pointeur, booleen) qui pemet de libérer le pointeur et de supprimer son occurence dans la map… [code] void CManagerMemoire::Libere(void *ptr, bool tableau) { //récupération du pointeur dans la map MapAlloc::iterator i=Allocations.find(ptr); try { //on n'est pas content si le pointeur ne fait pas partie de ceux qui sont gérés if(i==Allocations.end()) throw std::invalid_argument("pointeur non gere par le manager"); //on se simplifie la vie, et on vérifie si on ne fait pas d'erreur //d'appel de delete/delete[] par rapport au new/new[] utilisé Bloc retrait=i->second; if(retrait.Tableau!=tableau) throw std::invalid_argument("erreur new delete[]/new[] delete"); //un affichage de base std::cout<<"liberation de "<<ptr<<std::endl; //suppression de l'occurence dans la mat Allocations.erase(ptr); //libération définitive du pointeur free(ptr); } catch(std::invalid_argument &e) { std::cout<<e.what()<<std::endl; system("PAUSE"); throw e; } }[/code] J'ai enfin surchargé globalement new, new[], delete et delete[] de manière à ce qu'ils appellent les méthodes correspondante (Alloue pour new et new[], Libere pour delete et delete[]) de la classe sous la forme de [code] inline void* operator new(std::size_t taille) { return CManagerMemoire::GetInstance().Alloue(taille, false); } inline void* operator new[](std::size_t taille) { return CManagerMemoire::GetInstance().Alloue(taille, true); } inline void operator delete(void *ptr) { CManagerMemoire::GetInstance().Libere(ptr, false); } inline void operator delete[](void *ptr) { CManagerMemoire::GetInstance().Libere(ptr, true); } [/code] Le problème que je rencontre, c'est que tous les essais que je fais fontctionnent sans aucun problème… du moment que j'essaie d'utiliser new[] et delete[] (et ce, même si je fais un new type[1]) alors que l'application ne s'initiallise meme pas correctement quand j'essaie de faire un new simple… Quelqu'un aurait-il une idée de la manière de résoudre ce problème[question] Merci d'avance [chinois]
 Afficher le profil de koala01 Envoyer un message privé à koala01
 
 
Publicité
 breizhbugs  Posté le 23/05/2006 à 15:28  
Astucien

3001 Messages
Salut, Juste pour dire de mettre le code qui te sert a faire des tests.
Afficher le profil de breizhbugs Voir la configuration de breizhbugsEnvoyer un message privé à breizhbugs
 Revenir en haut de la page
 koala01  Posté le 23/05/2006 à 15:55  
Astucien

4715 Messages
Ben, c'est tout simple: un fichier entete "enabledebug.h" construit en [code] //a commenter pour annuler le tout #define DEBUG #ifdef DEBUG #ifndef ENABLEDEBUG_H #define ENABLEDEBUG_H //inclusion pour avoir std::size_t #include <iostream> //inclusion du gestionnaire de mémoire #include "cmanagermemoire.h" inline void* operator new(std::size_t taille) { return CManagerMemoire::GetInstance().Alloue(taille, false); } inline void* operator new[](std::size_t taille) { return CManagerMemoire::GetInstance().Alloue(taille, true); } inline void operator delete(void *ptr) { CManagerMemoire::GetInstance().Libere(ptr, false); } inline void operator delete[](void *ptr) { CManagerMemoire::GetInstance().Libere(ptr, true); } #endif //ENABLEDEBUG_H #endif //DEBUG [/code] et dans le fichier principal [code] //les classiques #include <cstdlib> #include <iostream> using namespace std; //activation du debuggage #include "enabledebug.h" int main(int argc, char *argv[]) { //creation de l'instance du gestionnaire de mémoire; CManagerMemoire &gestmem=CManagerMemoire::GetInstance(); (...) } [/code] alors sont OK les codes basés sur [code] struct mastruct{ (...) }; mastruct *obj1=new mastruct[1]; mastruct *obj1=new mastruct[n];//ou n est n'importe quel entier int *entier=new int[1]; int *entier=new int[n]; char *caractere=new char[1]; char *caractere=new char[n]; n_importe_quel_type *un_nom=new n_importe_quel_type[kkechose]; [/code] Le delete[] fonctionne alors également très bien... foirent systématiquement les codes basés sur [code] mastruct *obj1=new mastruct; int *entier=new int; char *caracter=new char; n_importe_quel_type *un_nom=new n_importe_quel_type; [/code] Je ne suis pas en mesure de tester le delete… simplement parce que l'application foire à l'initialisation bien avant que le new ne soit lancé… La compilation et le linking ne présentent aucun problème, mais, à l'exécution, meme la création de l'instance du gestionnaire de mémoire ne va pas à son terme. Quand on rajoute un fichier de sortie ("fuitesmemoire.log"), le fichier est créé, mais, alors que l'on demande d'y écrire un "titre" dans le constructeur du gestionnaire de mémoire, l'application s'arrete sans meme effectuer cette écriture…
Afficher le profil de koala01 Voir la configuration de koala01Envoyer un message privé à koala01
  Revenir en haut de la page
 AlexPrince  Posté le 23/05/2006 à 16:05  
Petit astucien

398 Messages
C'est absolument illisible. Les tags de code sont absolument monstrueux et devraient être changés. J'te propose de coller ton code là, de peser sur le bouton paste et de nous envoyer le lien. http://www.code-dynasty.net/paste/
Afficher le profil de AlexPrinceEnvoyer un message privé à AlexPrince
 Revenir en haut de la page
 koala01  Posté le 23/05/2006 à 16:22  
Astucien

4715 Messages
AlexPrince a écrit :
C'est absolument illisible. Les tags de code sont absolument monstrueux et devraient être changés. J'te propose de coller ton code là, de peser sur le bouton paste et de nous envoyer le lien. http://www.code-dynasty.net/paste/
Avec quoi tu viens toi[question][question][devil][feroce] Je suis tout à fait d'accord avec le fait que de ne pas pouvoir formater l'apparence d'un code quand on utilise [ code ][ / code ] rend les chose beaucoup plus difficile à suivre, mais quel nom est plus compréhensible pour une structure que mastruct, pour un entier que entier, ou pour un caractere que caractere quand il s'agit de donner un exemple de code [question] Si tu n'es pas capable de comprendre qu'un commentaire n'a d'intéret que quand il précède ce qu'il commante, je ne pourrai rien faire pour toi… d'autant plus que le code est en lui meme suffisemment indenté pour savoir ce qui se relie à quoi… Mais ne viens alors jamais me demander de relire un de tes codes si tu ne travailles pas comme cela… Si au moins ta remarque était constructive, on aurait pu discuter entre gens civilisés, mais, encore une fois, parce que l'on a le malheur de rentrer dans le moule (très mauvais au demeurant) que souhaite MON SIEUR, voilà qu'il se met à critiquer sans raison…
Afficher le profil de koala01 Voir la configuration de koala01Envoyer un message privé à koala01
  Revenir en haut de la page
 koala01  Posté le 23/05/2006 à 16:29  
Astucien

4715 Messages
Ce coup de sang étant passé, si quelqu'un souhaite voir le code en entier, et avec une certaine "coloration synthaxique", il trouvera l'exportation au format HTML des différents fichier [url="http://koala01.free.fr/gestmem"]==>ICI<==[/url]
Afficher le profil de koala01 Voir la configuration de koala01Envoyer un message privé à koala01
  Revenir en haut de la page
 breizhbugs  Posté le 23/05/2006 à 16:52  
Astucien

3001 Messages
[hello] Je suis pas sur mais je pense que c'est parce que "inline void* operator new(std::size_t taille)" n'as pas de taille par defaut? D'ailleurs quand tu fais "mastruct *obj1=new mastruct;", comment le new fait pour connaitre la taille a allouer, cad la taille en byte de mastruct?
Afficher le profil de breizhbugs Voir la configuration de breizhbugsEnvoyer un message privé à breizhbugs
 Revenir en haut de la page
 koala01  Posté le 23/05/2006 à 17:14  
Astucien

4715 Messages
C'est là que tu te trompes… En fait, l'opérateur "new" est lui meme une surcharge de (type)malloc(sizeof(type)) … qui, pour etre précis, commence par allouer la mémoire grace à malloc puis appelle le constructeur de ta classe (ton type) pour placer les différents éléments à leurs places respectives… La taille est donc implicitement gérée par new, grace au fait que tu fournis un type qui lui a une taille connue… La meilleure preuve en est que, si tu crées un projet console tout bete avec le code que je fournis, si tu demande un new mastruct[n] tu verra qu'il alloue effectivement n fois (taille d'un entier+ taille de 10 caractères) (autrement dit n fois 16 octets)… Le problème est que cela fonctionne sans problème tant que j'essaye d'allouer des tableaux sur ma structure (ma classe ou n'importe quel type connu par le programme au moment de la tentative d'allocation), mais que cela foire systématiquement quand il s'agit d'allouer un seul objet de ce type… (du moins, si je n'utilise pas new montype[1]) Et pourtant, il n'y a aucune raison à cela… ou du moins, je n'arrives pas à en déterminer la raison… Maintenant, peut etre tout simplement mon compilo qui bug sur ce coup là…

Modifié par koala01 le 23/05/2006 17:22
Afficher le profil de koala01 Voir la configuration de koala01Envoyer un message privé à koala01
  Revenir en haut de la page
 koala01  Posté le 23/05/2006 à 18:20  
Astucien

4715 Messages
Si tu es intéressé par le fait de voir le fonctionnement en entier (à ceci près qu'il faut encore gérer quelques erreurs, comme l'impossiblité d'ouvrir le fichier de log), tu le code final [url="http://koala01.free.fr/gestmemfinal"]==>ICI<==[/url]
Afficher le profil de koala01 Voir la configuration de koala01Envoyer un message privé à koala01
  Revenir en haut de la page
 breizhbugs  Posté le 23/05/2006 à 21:48  
Astucien

3001 Messages
Salut, Bon d'apres mes tests: - aucun de tes new ne sont appelées (j'ai mis des std::cerr un peu partout en fait). - sinon quand on fait un log file, on ouvre, on ecrit et on ferme le fichier dans une seule et meme fonction, car si crash quand le fichier est ouvert, on perd les données il me semble. - j'ai une floppé d'appel a delete alors que c'est censee etre delete[], aucun appel a new!
Afficher le profil de breizhbugs Voir la configuration de breizhbugsEnvoyer un message privé à breizhbugs
 Revenir en haut de la page
 koala01  Posté le 23/05/2006 à 23:49  
Astucien

4715 Messages
Alors, il y a un sérieux problème… Soit parce que tu aurais commenté le "#define DEBUG" (première ligne du fichier enabledebug.h), soit parce qu'il n'est purement et simplement pas pris en compte lors de la compilation… Avec dev-c++, il faut demander de compiler tous les fichiers apres avoir rajouté ce fichier au projet, c'est peut etre de là que ca vient…(car je t'assure que chez moi, les appels à new sont bien envoyé vers la classe CManagerMemoire [clindoeil]) En C, tu as raison, il vaut mieux travailler avec le fichier en une seule fois… En C++, le besoin est beaucoup moins impératif grâce au fait que la classe ofstream est très particulièrement sécurisée… La meilleure preuve est que, si tu lance l'application juqu'au premier "appuyez sur une touche",tu peux parfaitement ouvrir le fichier créé avec un autre éditeur de textes… Ceci dit, il semblerait que ce ne soit pas le new qui pose problème, mais le delete… en effet l'utilisation de new avec delete[] nous envoie l'erreur (ce qui est logique), l'utilisation de new[] avec delete[] fonctionne parfaitement, mais dés que l'on essaye d'utiliser delete (que ce soit avec new ou new[], à bon escient ou non), ca foire… Je pourrais donc me tourner vers une solution "pis aller", mais elle ne convaint pas… En effet, je pourrais décider de supprimer l'implémentation du inline void delete(void *ptr) et d'utiliser systématiquement delete[] pour libérer les pointeurs. Il "suffirait" pour cela que je ne lance pas l'exception invalid_argument dans libere()… En effet, d'après mes lecture, il est tout à fait légal d'utiliser delete[] alors que l'on a utilisé new… Le problème est alors qu'aucune utilisation de delete ne sera prise en compte par le gestionnaire de mémoire, et donc qu'il indiquera des fuites qui n'existent pas… Comme je le saurais, je pourrais m'en accomoder, mais je perdrais énormément en "portabilité" ou en possiblités de développement en groupe… En effet, que quelqu'un utilise (logiquement) delete apres un new ou qu'il l'utilise simplement parce qu'il "a oublier d'utiliser delete[]", et il s'étonnera "d'avoir une soi disant fuite mémoire alors qu'il a correctement tout libéré"…
Afficher le profil de koala01 Voir la configuration de koala01Envoyer un message privé à koala01
  Revenir en haut de la page
 AlexPrince  Posté le 24/05/2006 à 05:39  
Petit astucien

398 Messages
koala01 a écrit :
AlexPrince a écrit :
C'est absolument illisible. Les tags de code sont absolument monstrueux et devraient être changés. J'te propose de coller ton code là, de peser sur le bouton paste et de nous envoyer le lien. http://www.code-dynasty.net/paste/
Avec quoi tu viens toi[question][question][devil][feroce] Je suis tout à fait d'accord avec le fait que de ne pas pouvoir formater l'apparence d'un code quand on utilise [ code ][ / code ] rend les chose beaucoup plus difficile à suivre, mais quel nom est plus compréhensible pour une structure que mastruct, pour un entier que entier, ou pour un caractere que caractere quand il s'agit de donner un exemple de code [question] Si tu n'es pas capable de comprendre qu'un commentaire n'a d'intéret que quand il précède ce qu'il commante, je ne pourrai rien faire pour toi… d'autant plus que le code est en lui meme suffisemment indenté pour savoir ce qui se relie à quoi… Mais ne viens alors jamais me demander de relire un de tes codes si tu ne travailles pas comme cela… Si au moins ta remarque était constructive, on aurait pu discuter entre gens civilisés, mais, encore une fois, parce que l'on a le malheur de rentrer dans le moule (très mauvais au demeurant) que souhaite MON SIEUR, voilà qu'il se met à critiquer sans raison…
Non mais... ta gueule... Je parlais du formatage du forum, pas de ton code. [code]class ZeroException { public: ZeroException() { } }; void * CManagerMemoire::Alloue(std::size_t taille, bool tableau) { // ... try { if(taille == 0) throw(ZeroException()); // ... } catch(ZeroException& ze) { taille = 1; throw(); } catch(...) { // ... } }[/code]Essaie ça.
Afficher le profil de AlexPrinceEnvoyer un message privé à AlexPrince
 Revenir en haut de la page
 koala01  Posté le 25/05/2006 à 13:17  
Astucien

4715 Messages
Non mais... ta gueule... Je parlais du formatage du forum, pas de ton code. [code]class ZeroException { public: ZeroException() { } }; void * CManagerMemoire::Alloue(std::size_t taille, bool tableau) { // ... try { if(taille == 0) throw(ZeroException()); // ... } catch(ZeroException& ze) { taille = 1; throw(); } catch(...) { // ... } }[/code]Essaie ça.
Hé, ho, tu ferais bien de rester un tout petit peu poli… Si pas vis à vis de moi, car je l'ai peut etre mérité, au moins vis à vis des responsables du forum qui sont déjà bien gentils de mettre un espace de discution à notre service… Si les capacités du forum ne te plaisent pas, sache qu'on ne te retient absolument pas… J'espérais, visiblement à tord qu'apres la dernière explication par message privé d'il y a pres d'un an, tu aurais un peu évolué, mais visiblement c'était encore te faire trop d'honneur… Mais tu te fourres le doigt dans l'oeil si tu crois que je vais me laisser marcher sur les pieds par un sale petit gamin de m[censure] qui n'est même pas capable de supporter qu'on lui réponde sur le ton qu'il a lui meme utilisé pour parler alors qu'on ne l'attaquait meme pas à ce moment là… En plus, sache que new doit renvoyer bad_alloc s'il échoue, et non une quelconque zeroexception. Sans compter que si tu avais pris un tout petit peu la peine de lire les différents codes que j'ai pris la peine de mettre en ligne, tu aurais remarqué que ce que tu me propose, c'est exactement ce qui est fait, les erreurs en moins… Ni le fait que, si tu avais un été un peu moins occupé à te regarder le nombril en te demandant pourquoi je t'agressais en réaction à ta propre agressivité, tu aurais vu que le porblème n'était pas au niveau de new mais bien au niveau de delete…

Modifié par koala01 le 25/05/2006 13:18
Afficher le profil de koala01 Voir la configuration de koala01Envoyer un message privé à koala01
  Revenir en haut de la page
 koala01  Posté le 25/05/2006 à 13:27  
Astucien

4715 Messages
breizhbugs==> (avec toi, au moins, il y a moyen de parler en gens civilisés [clindoeil]) Ta remarque concernant le fichier log m'a incité à revoir un peu la manière dont je le gérais… J'ai donc décidé de ne pas mettre le fichier log en tant que membre de la classe, et de modifier quelques peut les structures utilisées (et les méthodes)… Le résultat se trouve[url="http://koala01.free.fr/gestmemfinal2"]==>ICI<==[/url] et *semble* fonctionner pour tous les cas (new, new[], delete, delete[] et avec erreur new[]delete/new delete[]) Il ne me reste plus qu'à essayer de la maltraiter un peu dans le cadre d'un projet un peu plus complexe [clindoeil]… Je te remercie grandement du soutien et des conseils que tu as pu m'apporter[clindoeil]
Afficher le profil de koala01 Voir la configuration de koala01Envoyer un message privé à koala01
  Revenir en haut de la page
 breizhbugs  Posté le 25/05/2006 à 15:07  
Astucien

3001 Messages
Salut koala, Je te trouve un peu dur avec alex: c'est pas parce que l'on apprecie pas quelques fonctionnalités du forum, que l'on n'apprecie pas le boutot des modos. La partie prog du forum etant assez peu fréquentée, si le peu de participants reguliers qui y vient se prends le choux c'est autant fermer cette section. Enfin, on ne peut pas connaitre le mode de fonctionnement de toutes les APIS de tous les languages, alors quand quelqu'un emet une suggestion qui va a l'encontre d'un mode de fonctionnement precis, c'est pas la peine de lui "rentrer dans le lard" non plus. (quand je demande 'D'ailleurs quand tu fais "mastruct *obj1=new mastruct;", comment le new fait pour connaitre la taille a allouer, cad la taille en byte de mastruct? ' et que tu commence à me repondre par "C'est là que tu te trompes…", ca donne pas trop envie de repondre(meme si tu as detailler le fonctionnement plus en detail apres). Bon je DL le code et je le teste un peu plus tard. Sinon une question: connais tu les 'CComPtr' sous windows qui sont des pointeurs intelligents qui sont encapsulé dans une classe. Pourquoi ne pas avoir fait un truc dans le genre? a+
Afficher le profil de breizhbugs Voir la configuration de breizhbugsEnvoyer un message privé à breizhbugs
 Revenir en haut de la page
 AlexPrince  Posté le 25/05/2006 à 16:28  
Petit astucien

398 Messages
Le problème est que cela fonctionne sans problème tant que j'essaye d'allouer des tableaux sur ma structure (ma classe ou n'importe quel type connu par le programme au moment de la tentative d'allocation), mais que cela foire systématiquement quand il s'agit d'allouer un seul objet de ce type… (du moins, si je n'utilise pas new montype[1])
Et bien sûr, je devais déduire que le problème était avec delete. Que suis-je bête... Pour ce qui est de ma suggestion, je sais très bien que new retourne bad_alloc quand il échoue... Il ne retourne 0 que si tu spécifies new(nothrow). À moi de te renvoyer la balle maintenant: si tu avais lu mon code quelque peu, tu aurais remarqué que je n'ai pas testé la valeur retournée par new mais plutôt la variable 'taille'. En effet, si tu passes 0 à malloc() tu obtiens un comportement indéfini qui pourrait très facilement être la cause d'un crash, d'où mon test. Edit: Petit commentaire en passant. Si tu ne sais pas écrire en anglais, ne fait pas semblant. Des trucs comme 'ManagerMemoire' ça fait pas très chic vois-tu. Utilise juste l'anglais ou juste le français parce que pour l'instant t'as l'air d'un clown avec ton code mi-anglais mi-français. 'GestionnaireMemoire' ou 'GestionMemoire' ou même encore 'GestionMem' feraient très bien l'affaire, ou alors, 'MemManager'. Continue comme ça mon champion.. [crazy]

Modifié par AlexPrince le 25/05/2006 16:32
Afficher le profil de AlexPrinceEnvoyer un message privé à AlexPrince
 Revenir en haut de la page
 koala01  Posté le 25/05/2006 à 17:32  
Astucien

4715 Messages
breizhbugs a écrit :
Salut koala, Je te trouve un peu dur avec alex: c'est pas parce que l'on apprecie pas quelques fonctionnalités du forum, que l'on n'apprecie pas le boutot des modos.
Vois tu, le problème est que j'ai survolé suffisemment de sujets sur lesquels alexprince réagit pour savoir qu'il est systématiquement tres agressif dans ses réponses, et qu'il ne supporte pas que l'on puisse lui en faire la remarque (ce qui était le sujet de la correspondance en message privé, et dans laquelle j'avais, soi dit en passant, mis énormément d'eau dans mon vin…)
La partie prog du forum etant assez peu fréquentée, si le peu de participants reguliers qui y vient se prends le choux c'est autant fermer cette section.
Sur ce point, je suis tout à fait d'accord avec toi… La seule chose que je rajouterai avant de clore le sujet, ces que certaines personnes feraient bien de respecter un tant soit peu les intervenants du forums s'ils veulent etre respecter en retour.
Enfin, on ne peut pas connaitre le mode de fonctionnement de toutes les APIS de tous les languages, alors quand quelqu'un emet une suggestion qui va a l'encontre d'un mode de fonctionnement precis, c'est pas la peine de lui "rentrer dans le lard" non plus. (quand je demande 'D'ailleurs quand tu fais "mastruct *obj1=new mastruct;", comment le new fait pour connaitre la taille a allouer, cad la taille en byte de mastruct? ' et que tu commence à me repondre par "C'est là que tu te trompes…", ca donne pas trop envie de repondre(meme si tu as detailler le fonctionnement plus en detail apres).
Excuse moi pour cet exces d'agressivité absolument injustifié [clindoeil][rougir]
Bon je DL le code et je le teste un peu plus tard. Sinon une question: connais tu les 'CComPtr' sous windows qui sont des pointeurs intelligents qui sont encapsulé dans une classe. Pourquoi ne pas avoir fait un truc dans le genre? a+
Je pourrais effectivement décider d'utiliser les pointeurs intelligents (plutot ceux de la STL, alors, car je souhaites que le projet dans lequel cela s'insérera soit le plus portable possible, ce qui fait que je ne voudrais pas utiliser quelque chose qui ne soit accessible que sous un système donné, raison pour laquelle je prévois de supprimer les appels à system("PAUSE")…) Mais maintenant que la classe *semble* fonctionner, je vais me faire un plaisir de l'utiliser… Alexprince==>
AlexPrince a écrit :
Le problème est que cela fonctionne sans problème tant que j'essaye d'allouer des tableaux sur ma structure (ma classe ou n'importe quel type connu par le programme au moment de la tentative d'allocation), mais que cela foire systématiquement quand il s'agit d'allouer un seul objet de ce type… (du moins, si je n'utilise pas new montype[1])
Et bien sûr, je devais déduire que le problème était avec delete. Que suis-je bête...
(c'est toi qui dit que tu es bete… je serai suffisemment bon pour décider de ne pas dire mon avis sur le sujet (car, si tu avais lu les autres messages… enfin bon…)
Pour ce qui est de ma suggestion, je sais très bien que new retourne bad_alloc quand il échoue... Il ne retourne 0 que si tu spécifies new(nothrow). À moi de te renvoyer la balle maintenant: si tu avais lu mon code quelque peu, tu aurais remarqué que je n'ai pas testé la valeur retournée par new mais plutôt la variable 'taille'. En effet, si tu passes 0 à malloc() tu obtiens un comportement indéfini qui pourrait très facilement être la cause d'un crash, d'où mon test.
Là ou tu as tout à fait raison, et je vais d'ailleurs me dépécher de modifier le code, c'est qu'il faut prévoir le cas où l'on essayerais effectivement d'allouer une taille nulle pour éviter les comportement aléatoires…
Edit: Petit commentaire en passant. Si tu ne sais pas écrire en anglais, ne fait pas semblant. Des trucs comme 'ManagerMemoire' ça fait pas très chic vois-tu. Utilise juste l'anglais ou juste le français parce que pour l'instant t'as l'air d'un clown avec ton code mi-anglais mi-français. 'GestionnaireMemoire' ou 'GestionMemoire' ou même encore 'GestionMem' feraient très bien l'affaire, ou alors, 'MemManager'.
Tu vas encore croire que je t'agresse de manière non justifiée, mais, à tout hasard, manager est tout à fait un terme francais également… Peut etre pas au canada, mais il est bel et bien dans mon Dictionnaire… Ceci dit, j'aurais effectivement pu décider d'un terme plus simple pour la classe
Continue comme ça mon champion.. [crazy]
Si je devais répondre à cela, je m'énerverais surement encore (mais de manière tout à fait injustifiée, n'est-ce pas [quetion]) Je préfères donc laisser les autres juges…
Afficher le profil de koala01 Voir la configuration de koala01Envoyer un message privé à koala01
  Revenir en haut de la page
 AlexPrince  Posté le 25/05/2006 à 23:51  
Petit astucien

398 Messages
Manager est un anglicisme... Mais si tu y tiens... 'GetInstance' est complètement anglophone.
Afficher le profil de AlexPrinceEnvoyer un message privé à AlexPrince
 Revenir en haut de la page
 koala01  Posté le 26/05/2006 à 02:55  
Astucien

4715 Messages
AlexPrince a écrit :
Manager est un anglicisme... Mais si tu y tiens... 'GetInstance' est complètement anglophone.
Alors, je vais essayer d'être clair tout en te parlant tout aussi calmement que possible… Oui, manager est un anglicisme, mais, afin d'améliorer ta culture générale, il faut savoir que beaucoup d'anglicismes sont, très souvent, à la base, des mots français récupérés par les anglais, avant d'etre des mots anglais… Je sais que le mot d'origine date, le plus souvent du Moyen-Age, mais les langues vivantes ont de tous temps récupéré des termes dans d'autres langues, et ce n'est pas pres de changer… Le malheur, si tu veux voir les choses sous cet angle, c'est qu'actuellement la langue véhiculaire majeure est l'anglais, et qu'il est donc logique que de nombreux emprunts y soient fait (on a encore de la chance: si les mots étaient en chinois ou en indou, on risquerait d'avoir beaucoup plus de mal [clindoeil]) Quand il s'agit, pour moi, de créer un assesseur ou un modificateur, effectivement, j'utilises sans vergogne les préfixes Get et Set, simplement parce que tout le monde comprend ce que cela veut dire, et que c'est beaucoup plus court à écrire que les équivalents francophones… En outre, de très nombreuse EDI, meme si elles sont en francais, te proposeront de créer "les méthodes set et get" quand tu leurs demandera de créer un membre dans une classe… Je ne vois pas vraiment ce qu'il peut y avoir de coquant là dedans… Ensuite, effectivement, il m'arrive d'utiliser des termes clairement anglais (quoi qu'il n'y ai que GET dans Get Instance qui le soit [clindoeil]), mais, si cela t'ennuies, je ne t'obliges nullement à utiliser mes codes… Le malheur de ta dernière intervention est que, de mon point de vue, elle a tendance à confirmer l'impression que je me fais de toi… Je me demande d'ailleurs pourquoi j'ai bien pu prendre la peine d'y répondre…

Modifié par koala01 le 26/05/2006 02:57
Afficher le profil de koala01 Voir la configuration de koala01Envoyer un message privé à koala01
  Revenir en haut de la page
 breizhbugs  Posté le 26/05/2006 à 13:21  
Astucien

3001 Messages
J'hesite: [img]http://yelims5.free.fr/Sport/PingPong.gif[/img] ou [img]http://yelims5.free.fr/Sport/_Escrime.gif[/img] ou [img]http://yelims5.free.fr/Sport/Boxe.gif[/img] (toujours pas tester le code...)
Afficher le profil de breizhbugs Voir la configuration de breizhbugsEnvoyer un message privé à breizhbugs
 Revenir en haut de la page
 breizhbugs  Posté le 26/05/2006 à 20:37  
Astucien

3001 Messages
re, Bon j'ai testé et ca plante! la memoire alloué dans le main est correctement liberer semble t il mais lors du rapport dans le destructeur il indique: *** 004508A8 élément de 16 octets alloué dans main.cpp ligne 16 libere -> normal *** 004501C8 tableau de 4522480 octets alloué dans ÐE ÐE ØE ØE àE àE èE èE ðE ðE øE øE E E E E E E E E E E (E (E ... -> pas normal. (un bloc.fichier pas initialisé?) Je ne m'y connais pas du tout en Map truc muche donc sais pas trop comment ca fonctionne pour modifier. Sinon une question je suis pas sur: [code] void * CManagerMemoire::Alloue(std::size_t taille, bool tableau, const std::string &fichier, int ligne) { Bloc nouveau; nouveau.Taille=taille; nouveau.Tableau=tableau; nouveau.Fichier=fichier; nouveau.Ligne=ligne; nouveau.Libere=false; try { void *ptr; if((ptr=malloc(taille))==NULL) throw std::bad_alloc(); Allocations[ptr]=nouveau; std::cout<<"allocation de "<<taille<<" octets pour "<<ptr<<std::endl; //std::cin.get(); return ptr; } catch(...) { std::cout<<"erreur d'allocation"<<std::endl; //system("PAUSE"); throw std::bad_alloc(); } } [/code] Concernant "Bloc nouveau", il appartient a la fonction et est donc liberer a la fin de celle ci. Cela suppose donc que "Allocations[ptr]=nouveau;" recopie nouveau dans le tableau c'est bien ca?

Modifié par breizhbugs le 26/05/2006 20:43
Afficher le profil de breizhbugs Voir la configuration de breizhbugsEnvoyer un message privé à breizhbugs
 Revenir en haut de la page
 koala01  Posté le 27/05/2006 à 00:15  
Astucien

4715 Messages
La std::map est, en fait, le pendant des vecteurs et autres piles et files (plus près des vecteurs, ceci dit [clindoeil])… Il s'agit d'un tableau associatif clé<-->valeur, et tu as parfaitement compris le fait que NomDeMap[cle]=valeur avait pour but de recopier valeur dans le tableau en lui associant la clé cle (qui n'est ici rien d'autre que l'adresse du pointeur que l'on vient d'allouer [clindoeil][langue]…) (désolé, le lien est en anglais, mais, dés que j'aurai un équivalent francais, tu l'auras [url="http://www.sgi.com/tech/stl/Map.html"]==>les infos sont ici<==[/url]) C'est vraiment bisard que ca plante chez toi, alors que cela fonctionne tout à fait correctement chez moi… J'aimerais beaucoup comprendre pourquoi cela fonctionne si bien chez moi et pas chez toi… Quel compilateur utilises tu, de manière à me faire une idée [question]
Afficher le profil de koala01 Voir la configuration de koala01Envoyer un message privé à koala01
  Revenir en haut de la page
 koala01  Posté le 27/05/2006 à 00:58  
Astucien

4715 Messages
Alors, à part le fait que j'ai supprimé certaines demande d'appuis sur une touche, je viens d'essayer de compiler le programme avec borland 6 (version entreprise)… Il fonctionne sans aucun problème (de meme que sous dev-c++), la seule différence que j'obtiennes est le fait que, compilé avec borland, j'obtiens les lignes du log sous la forme de
*** 9459928 élément de 4 octets alloué dans C:\Documents and Settings\phil\Bureau\essai2\src\main.cpp ligne 14 libere
et que sous dev-c++, j'obiens le log sous la forme de
*** 0x3d2480 élément de 4 octets alloué dans src/main.cpp ligne 14 !!!non libéré !!!
(autrement dit, l'un avec le chemin absolu, et l'autre avec le chemin relatif) Ne t'en fais pas trop, mais cela, je présumes que tu t'en doutes, pour les accents dans la console (les é deviennent Ù) la sortie est en fait formatée pour etre correcte dans le fichier log (et, comme tout le monde sait bien que microsoft n'est meme pas capable d'accorder sa console avec le reste du système [langue][rougir])
Afficher le profil de koala01 Voir la configuration de koala01Envoyer un message privé à koala01
  Revenir en haut de la page
 AlexPrince  Posté le 27/05/2006 à 05:41  
Petit astucien

398 Messages
Sans vouloir t'offenser... c'est ton programme qui a le problème. La console peut très bien afficher des caractères accentués et autres. Tu dois alors utiliser wchar_t au lieu de char. http://www.opengroup.org/pubs/online/7908799/xsh/stddef.h.html Edit: De toutes évidence ça ne fonctionne pas mais je me souviens avoir testé un programme fait par quelqu'un d'autre qui avait été capable de faire fonctionner les accents dans la console.

Modifié par AlexPrince le 27/05/2006 05:46
Afficher le profil de AlexPrinceEnvoyer un message privé à AlexPrince
 Revenir en haut de la page
 breizhbugs  Posté le 27/05/2006 à 13:27  
Astucien

3001 Messages
Re, Avant d'envoyer une chaine sur la console(sous windows en tout cas), il faut faire un 'ansitooem' ou un truc dans le genre. En fait j'ai modifier les operateurs new/delete pour qu'ils affichent a message genre: [code] inline void operator delete(void *ptr) { std::cout << "operator del:\t" << ptr << std::endl; CManagerMemoire::GetInstance().Libere(ptr, false); }; [/code] Et il se trouve que j'ai des appels aux 'delete' bien apres la derniere instruction et apres meme que le destructeur de CmanagerMemoire soit terminé! Je suis sous VC++ .net 2002.

Modifié par breizhbugs le 27/05/2006 13:28
Afficher le profil de breizhbugs Voir la configuration de breizhbugsEnvoyer un message privé à breizhbugs
 Revenir en haut de la page
 koala01  Posté le 27/05/2006 à 16:09  
Astucien

4715 Messages
breizhbugs a écrit :
Re, Avant d'envoyer une chaine sur la console(sous windows en tout cas), il faut faire un 'ansitooem' ou un truc dans le genre. En fait j'ai modifier les operateurs new/delete pour qu'ils affichent a message genre: [code] inline void operator delete(void *ptr) { std::cout << "operator del:\t" << ptr << std::endl; CManagerMemoire::GetInstance().Libere(ptr, false); }; [/code] Et il se trouve que j'ai des appels aux 'delete' bien apres la derniere instruction et apres meme que le destructeur de CmanagerMemoire soit terminé! Je suis sous VC++ .net 2002.
Oui, de fait, j'avais résolu ce problème, mais apres avoir placé le code… Tous les liens sont maintenants prévus pour se rendre au bon endroit [clindoeil] J'en ai d'ailleurs profité pour "écarteler" le fichiers cexceptions en plusieurs fichiers selon l'origine de l'exception qui est lancée, et pour mettre le tout dans un espace de nommage… Hier, à la lecture d'un document très correct sur la STL, je me posais la question de savoir si ton compilateur supportait les constructeurs par défaut… Vu son "age", ce devrait etre le cas… Il s'agit d'un document de 62 pages, en PDF, dont je ne retrouve pas le lien pour te permettre de le télécharger si tu le souhaites… S'il t'intéresse, je le tiens à ta disposition [clindoeil] Je te remercie de l'idée de ansitooem, mais, malheureusement, il *semble* que l'instruction soit réservée à windows, et, dans de telles conditions, je préfères m'en passer (quand on se met à vouloir la protabilité [clindoeil][langue]) Dans l'ensemble (pour répondre, par la meme occasion à AlexPrince), le wchar_t ne résoudra qu'une partie des problèmes, dépendamment des locales définies pour la console, et posera en plus le problème de ne plus etre du texte "brut", car codé sur deux octets… A mon sens, dés qu'un projet devient important, le nombre d'allocations/libérations mémoires atteind très rapidement des sommets… L'affichage de l'ensemble de celles-ci dans une console en sortie de programme ne me semble pas *forcément* des plus adapté au travail de la personne qui est face à son clavier… Ici, sur le programme d'exemple, avec une ou deux allocations, on peut se permettre de les montrer, surtout que cela permet de se faire une idée du fonctionnement, mais en production, la seule sortie console serait vraissemblablement plutot le rapport cumulé des fuites et non la ribambelle de celles-ci et de la suite des opérations qui y a mené… Je suis ouvert à toute discution (constructive) sur le sujet, mais, personnellement, je préfères éplucher un tel rapport imprimé que de m'écarquiller les yeux sur une sortie console…
Afficher le profil de koala01 Voir la configuration de koala01Envoyer un message privé à koala01
  Revenir en haut de la page
 koala01  Posté le 27/05/2006 à 16:20  
Astucien

4715 Messages
Alexprince==> cela te fera peut etre plaisir de savoir qu'effectivement j'ai changé le nom de la classe… c'est devenu CGestMemoire [clindoeil] (par contre, tu risque de tiquer en voyant le nom de l'espace de nommage: "Debugging"[boom][boom])
Afficher le profil de koala01 Voir la configuration de koala01Envoyer un message privé à koala01
  Revenir en haut de la page
 breizhbugs  Posté le 27/05/2006 à 18:52  
Astucien

3001 Messages
Bon j'ai DL la nouvelle version et je testerai plus tard...
Afficher le profil de breizhbugs Voir la configuration de breizhbugsEnvoyer un message privé à breizhbugs
 Revenir en haut de la page
Haut de la page 
Inscrivez-vous !
- Posez vos questions

- Résolvez vos problèmes

- Aidez les autres

- Participez et créez vos discussions

- Dialoguez en privé avec d'autres membres

- Suivez vos sujets préférés

- Affichez les signatures des membres

TOUT EST GRATUIT !

Je crée mon compte




Vous avez besoin d'aide ?
Des centaines d'experts sont à votre disposition sur les forums PC Astuces pour vous aider gratuitement, 24h/24, 7j/7.

Les derniers sujets résolus !
 

 > Tous les forumsAutres langages

 
Forum PC Astuces© 1997-2008 WebastucesAller en haut de la page