IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Surcharge de delete


Sujet :

C++

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    396
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2006
    Messages : 396
    Par défaut Surcharge de delete
    Bonjour,

    J'esseye de faire un memoryManager basé sur ce tutorial : http://loulou.developpez.com/tutorie...artie1/#L2.2.1

    J'ai donc un fihcier test.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include <iostream>
    using namespace std;
     
    #include "debugNew.h"
     
    int main(void)
    {
    	int *p = new int;
    	delete p;
    	return 0;
    }
    Un fichier debugNew.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    #ifndef DEBUGNEW_H
    #define DEBUGNEW_H
     
    #include "CMemoryManager.h"
     
    inline void* operator new(std::size_t size, const char *file, int line)
    {
    	cout<<"alloc"<<endl;
    	return CMemoryManager::instance().allocate(size, file, line, false);
    }
     
    inline void operator delete(void *ptr) throw()
    {
    	cout<<"desalloc"<<endl;
    	CMemoryManager::instance().release(ptr, false);
    }
     
    #endif
     
    #ifndef new
        #define new new(__FILE__, __LINE__)
    #endif
    Le CMemoryManager.cpp:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #include "CMemoryManager.h"
    using namespace std;
     
    CMemoryManager &CMemoryManager::instance(void)
    {
        static CMemoryManager inst;
        return inst;
    }
     
    void *CMemoryManager::allocate(size_t size, const char *file, int line, bool array)
    {
    	void* ptr = malloc(size);
    	return ptr;
    }
     
    void CMemoryManager::release(void* ptr, bool array)
    {
    	free(ptr);
    }
    Et pour finir le CMemoryManager.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    #ifndef CMEMORYMANAGER_H
    #define CMEMORYMANAGER_H
     
    #include <iostream>
    #include <map>
    #include <fstream>
    #include <stack>
    #include <stdlib.h> //for malloc and free
     
    class CMemoryManager
    {
    	public:
    		static CMemoryManager &instance(void);
     
    		void *allocate(std::size_t, const char *, int, bool);
    		void release(void *, bool);
    	private:
    		CMemoryManager(void){};
    		~CMemoryManager(void){};
     
    		struct TBlock
    		{
    			std::size_t size;
    			const char *file;
    			int line;
    			bool array;
    		};
    		std::map<void*, TBlock> mBlocks;
    		std::stack<TBlock> mDeleteStack;
    };
     
    #endif
    A la compilation : tout ce passe bien.
    Mais voici le résultat de l'éxécution:
    alloc
    desalloc
    terminate called after throwing an instance of '__gnu_cxx::recursive_init'
    what(): N9__gnu_cxx14recursive_initE
    Abandon
    Et si je met cette ligne en commentaire : "CMemoryManager::instance().release(ptr, false);", voici le resultat:
    alloc
    desalloc
    desalloc
    desalloc
    desalloc
    desalloc
    Pourquoi ai-je cette erreur ?

    Merci d'avance...

  2. #2
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2006
    Messages : 366
    Par défaut
    Salut,

    J'avais également une erreur du type, le déboggueur montrait qu'en fait c'était un appel récursif de delete dans le fichier de la lib STL définissant la map. Bref, pour éviter ça j'avais dû faire un appel à CMEmoryManager::instance() avant toute allocation (en gros c'était ma première ligne du main). Maintenant je me souviens de personnes ayant eu un problème similaire, pour lesquelles ma solution n'avait pas marché, donc à tester mais je ne garantis pas que ça fonctionne. Il y a déjà eu un topic sur ce problème il me semble sur le fofo, une recherche devrait t'en apprendre plus.

    Autre chose : comme dit dans le tutoriel de Laurent Gomilla et comme spécifié par la norme, à chaque opérateur new doit correspondre un opérateur delete équivalent (c'est àdire prenant les mêmes paramètres), ça manque dans ton code.

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    396
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2006
    Messages : 396
    Par défaut
    Merci pour ta réponse...je vais voir ce que je peux trouver à ce sujet

    Pour ce qui est de l'opérateur delete équivalent à new, je ne l'ait pas mis ici pour vous éviter de lire trop de code

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    396
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2006
    Messages : 396
    Par défaut
    J'ai esseyé de mettre CMemoryManager::instance(); au début de mon main et toujours le même problème...

    Autrement il y a la solution du flag que j'ai trouvé dans un de tes posts mais c'est pas trop élégant : http://www.developpez.net/forums/sho...ght=map+delete

    J'ai aussi pensé à une autre solution:
    Mettre les fonctions membres allocate, release et nextDelete ainsi que la map et le stack en static, comme ça plus besoin de la fonction membre "instance()" : quand pensez-vous ? Y a-t-il des inconvénients ? (j'ai testé cette solution et ça fonctionne)

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    125
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 125
    Par défaut
    Voici un lien sur le meme sujet et avec le meme pb
    http://www.developpez.net/forums/sho...d.php?t=247404

    et pour la reponse changez les options de compiles style O2 ca devrait marcher

  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    396
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2006
    Messages : 396
    Par défaut
    Hum...je vient de lire tout le post et ça fait pas très pro de devoir mettre l'option O2.
    Et qui nous dit que sur d'autre compilateur, ça ne va pas planter ?!

    Donc je préfère quand même mettre tout en static...

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    125
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 125
    Par défaut
    c'est pas le O2 qui le fait marcher
    mais toutes commandes d'optimisations

    l'interception du new via une macro et l'interception du delete est quand meme un truc un peut space désolé si le compilo marche pas comme tu veux
    mais ca marche avec le mode debug et le 02
    Sinon je vois pas trop l'interet de compiler sans les options.

  8. #8
    Invité
    Invité(e)
    Par défaut
    c'est quoi ce malloc() dans du code C++ ???

  9. #9
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Citation Envoyé par toxcct
    c'est quoi ce malloc() dans du code C++ ???
    C'est du bas niveau. On aurait pu utiliser HeapAlloc(...), operator new(...), ou encore new char[...] ; peu importe là le but est d'allouer de la mémoire brute.
    Et puis de toute façon ils finiront tous par passer par la même fonction système.

  10. #10
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    malloc n'est en général pas un appel système.
    Sous POSIX, les appels systèmes utilisés seraient mmap ou brk.

  11. #11
    Membre Expert
    Avatar de Patriarch24
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2003
    Messages
    1 047
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 047
    Par défaut
    c'est pas le O2 qui le fait marcher
    mais toutes commandes d'optimisations

    l'interception du new via une macro et l'interception du delete est quand meme un truc un peut space désolé si le compilo marche pas comme tu veux
    mais ca marche avec le mode debug et le 02
    Sinon je vois pas trop l'interet de compiler sans les options.
    Un code qui fonctionne seulement grâce à des options de compilation est sans doute à revoir (sinon c'est le compilo qui est à revoir).

  12. #12
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Il ne faut pas se voiler la face : ce code (que j'ai écrit) est clairement de la bidouille pratique, plus que du joli code C++. Rien que redéfinir new / delete, c'est interdit par la norme. L'important est qu'en pratique ça marche dans 95% des cas, et que dans ces 95% de cas le développeur possède un outil pratique de gestion de la mémoire. Dans le cas où ça ne veut pas marcher, on sera simplement amputé d'un outil qui n'est pas indispensable.

    Maintenant, pour ceux qui voudraient pinailler, je suis certain qu'il existe de meilleures méthodes pour gérer les allocations de mémoire (soit en utilisant des fonctions obscures de l'OS, soit en forçant l'utilisateur a adopter une syntaxe plus verbeuse pour ses allocations).

  13. #13
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Laurent Gomila
    Rien que redéfinir new / delete, c'est interdit par la norme.
    Je n'ai pas ete voir comment tu le fais precisement, mais
    Citation Envoyé par ISO/IEC 14882
    18.4.1.1/2 Replaceable: a C++ program may define a function with this function signature [void* operator new(std::size_t size) throw(std::bad_alloc)] that displaces the default version defined by the C++ Standard library.
    et c'est la meme chose pour les formes arrays, nothrow et les versions correspondantes de delete. Voir aussi 17.4.3.4.

  14. #14
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    J'ai mal choisi le terme, je ne parle pas des surcharges qui elles sont OK. Je voulais dire, créer une macro dont l'identifiant est un mot-clé du langage :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define new new(__FILE__, __LINE__, ...)

  15. #15
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Laurent Gomila
    J'ai mal choisi le terme, je ne parle pas des surcharges qui elles sont OK.
    Il n'y a pas que les surchages qui sont autorisees. Tu peux aussi remplacer la version fournie par la bibliotheque. Et ca

    Je voulais dire, créer une macro dont l'identifiant est un mot-clé du langage :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define new new(__FILE__, __LINE__, ...)
    si c'est effectivement une mauvaise idee, tu peux quand meme le faire tant que tu n'inclus pas apres un en-tete standard (par contre tu ne peux pas le faire pour and, or, xor, bitor, bitand, compl, not, and_eq, xor_eq, or_eq, not_eq qui ne sont pas des keywords mais des tokens alternatifs ).

  16. #16
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet
    si c'est effectivement une mauvaise idee, tu peux quand meme le faire tant que tu n'inclus pas apres un en-tete standard
    Ah, il me semblait avoir lu que la norme parlait d'un comportement indéfini dans ce genre de cas.

    Citation Envoyé par Jean-Marc.Bourguet
    (par contre tu ne peux pas le faire pour and, or, xor, bitor, bitand, compl, not, and_eq, xor_eq, or_eq, not_eq qui ne sont pas des keywords mais des tokens alternatifs ).
    Alors ça... ça m'intéresse cette histoire de tokens alternatifs. C'est quoi ?

  17. #17
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Laurent Gomila
    Ah, il me semblait avoir lu que la norme parlait d'un comportement indéfini dans ce genre de cas.
    C'est bien un comportement indefini si on lit des entetes standards. Sinon, l'analyse des keywords se fait en phase 7, tandis que le preprocesseur c'est la phase 4.

    Alors ça... ça m'intéresse cette histoire de tokens alternatifs. C'est quoi ?
    Tu es sur que tu veux savoir... bon les caracteres {, }, [, ], #, &, |, ^, ~ posent des problemes parce qu'ils sont en dehors de certains jeux de caracteres. Un premier essai -- en C90 -- pour les definir en fonction des autres a ete les trigraphes: ??= #, ??/ \, ??' ^, ??( [, ??) ], ??! |, ??< {, ??> }, ??- ~. Mais les trigraphes etant definis comme une substitution de caracteres (en phase 1), cela pose des problemes d'une part, et d'autre part, c'est pas particulierement agreable a utiliser (meme si c'est mieux que de ne pas les avoir dans les cas ou ils sont necessaires).

    Un deuxieme essai -- en C++ et en C99 --, c'est de definir des "token alternatifs" pour les tokens qui utilisent ces caracteres. Certains tokens alternatifs (<% {, %> }, <: [, :> ], %: #, %:%: ##) ont une forme de tokens normaux (on les appelles les digraphes), d'autres (ceux que j'ai deja cites) ressemblent a des identificateurs. Mais comme ce sont des tokens alternatifs, ils sont traites comme des tokens du preprocesseurs des la phase 3 tandis que les keywords restent des identificateurs du preprocesseurs jusqu'en phase 7.

    Tu remarqueras eventuellement, qu'on founit une alternatives pour ! et != avec les tokens alternatifs mais pas avec les trigraphes. Je n'en connais pas la raison.

Discussions similaires

  1. Surcharge de delete[] et utilisation de ofstream
    Par qnop dans le forum Langage
    Réponses: 4
    Dernier message: 23/02/2012, 14h26
  2. surcharge de delete : recursive_init_error
    Par apesle dans le forum C++
    Réponses: 3
    Dernier message: 05/02/2009, 14h58
  3. surcharge operateur delete et héritage
    Par Hervé dans le forum C++
    Réponses: 5
    Dernier message: 29/03/2006, 13h59
  4. Réponses: 3
    Dernier message: 23/08/2005, 11h02
  5. Namespace et surcharge operator new/delete
    Par ZeLegolas dans le forum C++
    Réponses: 11
    Dernier message: 26/07/2005, 13h55

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo