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

Langage C++ Discussion :

Surcharge de delete[] et utilisation de ofstream


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Mars 2006
    Messages
    209
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 209
    Par défaut Surcharge de delete[] et utilisation de ofstream
    Bonjour à vous tous !!.

    Je suis actuellement en train de coder un mini gestionnaire de mémoire, dont je suis plutôt fier car il fonctionne parfaitement, enfin, presque^^.
    Sous windows, le code fonctionne parfaitement bien, mais il me semble fonctionner différemment sous Ubuntu.
    Je m'explique, lorsque mon gestionnaire ouvre le fichier de log, le premier appelle a l'opérateur surcharger delete[](void*), il est en fait appeler 2 fois, contre une fois pour les appels suivants. Cela est plutôt problèmatique, car ça me provoque un segfault. Je rappelle que ceci n'arrive pas sous Windows 7(enfin du moins chez moi^^).
    Le plus bizarre, c'est que le code ne me provoque aucun segfault et est clean du côté de valgrind si le fichier n'est pas ouvert ^^.

    On peut évidemment utiliser l"opérateur delete au lieu de delete[], mais après, ça ne fais pas super propre ^^.

    Voilà donc le code ^^
    main.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 "memoire.h"
     
    using namespace std;
     
    int main(void)
    {
        int *p = new int[50];
        int *d = new int;
        double *c = new double[298];
     
        double *pd = new double;
     
        delete p;
        delete pd;
        delete[] d;
        delete[] c;
     
        return 0;
    }
    memoire.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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    #ifndef MEMOIRE_H_INCLUDED
    #define MEMOIRE_H_INCLUDED
     
    #include <iostream>
    #include <cstdlib>
    #include <fstream>
     
    namespace qgm
    {
        class Memory
        {
            public :
                static Memory &instance(void);
     
                void *allocate(std::size_t, unsigned, char const*, bool);
                void  desallocate(void*, bool);
     
                char const *getFileDelete(void);
                unsigned getLineDelete(void);
     
                void prepareDelete(unsigned, char const*);
     
            private :
                /* Constructeur et destructeur privé */
                Memory(void);
                ~Memory(void);
     
                /* Block de mémoire */
                struct TBlock
                {
                    void *data; /* Pointeur alloué */
                    std::size_t size; /* Taille */
                    unsigned line; /* Ligne de l'allocation */
                    char const *file; /* Fichier de l'allocation */
                    bool array; /* L'objet allouer est ce un tableau ? */
     
                    TBlock *before; /* Block précedant */
                    TBlock *next; /* Block suivant */
                };
     
                struct TBlock_Control
                {
                    std::size_t allocation; /* Nombre d'allocation */
     
                    TBlock *first; /* Premier block */
                    TBlock *last; /* Dernier block */
                };
     
                TBlock_Control m_Block;
     
                /** Fichier et ligne de la désallocation **/
                char const *m_FDelete;
                unsigned    m_LDelete;
     
                std::ofstream m_File;/* Fichier de sortie de l'allocation */
        };
    }
     
    inline void* operator new(std::size_t s, unsigned l, char const *f)
    {
        return qgm::Memory::instance().allocate(s, l, f, false);
    }
     
    inline void* operator new[](std::size_t s, unsigned l, char const *f)
    {
        return qgm::Memory::instance().allocate(s, l, f, true);
    }
     
    inline void operator delete(void *p)
    {
        qgm::Memory::instance().desallocate(p, false);
    }
     
    inline void operator delete[](void *p)
    {
        qgm::Memory::instance().desallocate(p, true);
    }
     
    inline void operator delete(void *p, unsigned l, char const *f)
    {
        qgm::Memory::instance().prepareDelete(l, f);
        qgm::Memory::instance().desallocate(p, false);
    }
     
    inline void operator delete[](void *p, unsigned l, char const *f)
    {
        qgm::Memory::instance().prepareDelete(l, f);
        qgm::Memory::instance().desallocate(p, true);
    }
     
     
    #define new new(__LINE__, __FILE__)
    #define delete  qgm::Memory::instance().prepareDelete(__LINE__, __FILE__);\
                    delete
     
    #endif // MEMOIRE_H_INCLUDED
    memoire.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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    #include "memoire.h"
     
    namespace qgm
    {
        Memory::
        Memory(void)
        {
            m_Block.allocation = 0;
            m_Block.first = NULL;
            m_Block.last = NULL;
     
            m_File.open("Rapport/Fuites de memoires.txt");
        }
     
        Memory::
        ~Memory(void)
        {
            /* Si on a aucune allocation de faîtes */
            if(m_Block.allocation == 0)
                m_File << "Aucune fuite de mémoire détecter.";
     
            /* Sinon on prévient le programmeur, et on libère la mémoire */
            else
            {
                std::size_t t = 0; /* Taille totale non libérer */
     
                TBlock *actu, *next;
     
                actu = m_Block.first;
     
                /* On libére les bloques un par un */
                do
                {
                    next = actu->next;
                    t += actu->size;
     
                    m_File  << "Libération automatique du pointeur allouer de :\n"
                            << actu->size << " octets dans le fichier : \n"
                            << actu->file << '(' << actu->line << ')'
                            << std::endl << std::endl;
     
                    free(actu->data);
                    free(actu);
                    actu = next;
                }while(actu != NULL);
     
                /* On dit de combien d'octets les fuites auraient eu lieu^^ */
                m_File << "Libération automatique de : " << t << " octets...";
            }
     
            m_File.close();
        }
     
        Memory &Memory::
        instance(void)
        {
            static Memory inst;
            return inst;
        }
     
        void *Memory::
        allocate(std::size_t s, unsigned l, char const *f, bool a)
        {
            /* On alloue p */
            void *p = malloc(s);
     
            /* On alloue un nouveau block */
            TBlock *block = (TBlock*)malloc(sizeof *block);
     
            /* Si une des allocations n'a pas fonctionner */
            if(block == NULL || p == NULL)
            {
                m_File  << "Impossible d'allouer " << s << " octets." << std::endl
                        << f << '(' << l << ')' << std::endl;
                return NULL;
            }
     
            /* On le configure */
            block->data  = p;
            block->size  = s;
            block->line  = l;
            block->file  = f;
            block->array = a;
     
            /* On vient de l'allouer, il n'y a pas de suivant */
            block->next  = NULL;
     
            /* Si la première allocation*/
            if(m_Block.allocation == 0)
            {
                /*Le premier block est le dernier */
                m_Block.first = block;
                block->before = NULL;
            }
     
            else
            {
                /* On configure l'ancien dernier block comme avant dernier */
                m_Block.last->next = block;
                block->before      = m_Block.last;
            }
     
            m_Block.allocation++;
     
            /* le dernier est donc celui la */
            m_Block.last = block;
     
            /** On écrit dans notre fichier de log **/
     
            m_File  << "Allocation de " << s << " octets" << std::endl
                    <<  f << '(' << l << ')' << std::endl << std::endl;
     
            return p;
        }
     
        void Memory::
        prepareDelete(unsigned l, char const *f)
        {
            m_LDelete = l;
            m_FDelete = f;
        }
     
        void Memory::
        desallocate(void *p, bool a)
        {
            TBlock *actu, *next, *before;
     
            /* On se place au premier block */
            actu = m_Block.first;
     
            while(actu != m_Block.last && actu->data != p)
                actu = actu->next;
     
            if(actu->data != p)
            {
                /* Si le pointeur n'a pas été allouer avec l'allocateur */
                m_File << "Mauvaise désallocation du pointeur " << p
                << " a la ligne " << m_LDelete << " du fichier : "
                << m_FDelete << std::endl;
     
                return;
            }
            /* On récupère les blocks précédant et suivant */
            next = actu->next;
            before = actu->before;
     
            /*  On fait rejoindre le block précédant avec le suivant
                Si c'est possible */
            if(next != NULL)
                next->before = before;
     
            if(before != NULL)
                before->next = next;
     
            /*  Si c'était le dernier block ou le premier block,
                On fait repointer les blocks de début et de fin */
            if(actu == m_Block.first)
                m_Block.first = next;
     
            if(actu == m_Block.last)
                m_Block.last  = before;
     
            m_Block.allocation--;
     
            /** On écrit dans notre fichier de log **/
     
            m_File  << "Désallocation du pointeur allouer d'une taille de :\n"
                    << actu->size << " octets " <<"dans le fichier :\n"
                    << actu->file << '(' << actu->line << ')'
                    << "\nEst désallouer dans le fichier :\n"
                    << m_FDelete << '(' << m_LDelete << ')'
                    << std::endl;
     
            /* Si on c'est tromper de delete([]) */
            if(actu->array != a)
            {
                m_File  <<  "Attention tout de même :\n"
                            "Ce pointeur n'a pas était désallouer "
                            "avec la bonne version de 'delete'"
                        << std::endl;
            }
     
            m_File << std::endl;
     
            /* On libère les pointeurs */
            free(p);
            free(actu);
        }
    }
    Merci de votre aide ^^

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Bonjour,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int *p = new int[50];
        int *d = new int;
        double *c = new double[298];
     
        double *pd = new double;
     
        delete p;
        delete pd;
        delete[] d;
        delete[] c;
    soit tu as mal copié/collé, soit tu te trompes dans le delete de p et d.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TBlock *block = (TBlock*)malloc(sizeof *block);
    est-ce normal que tu n'alloues pas sizeof(TBlock*) ?

    Erreur de recopie ou tu n'utilises pas tes opérateurs surchargés ? Où sont les paramètres supplémentaires de ton new ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int *p = new (__LINE__, __FILE__) int[50];
        int *d = new (__LINE__, __FILE__) int;
        double *c = new (__LINE__, __FILE__) double[298];
     
        double *pd = new (__LINE__, __FILE__) double;
     
        delete[] p;
        delete pd;
        delete d;
        delete[] c;
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Membre confirmé
    Inscrit en
    Mars 2006
    Messages
    209
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 209
    Par défaut
    Salut.

    Le fait de ce trompé de delete est totallement volontaire.
    En effet, si je me trompe de delete, on peut tout de même free le malloc, mais je préviens l'utilisateur qu'il s'est tromper de delete a telle ligne ^^^.

    Pour le sizeof, ça revient exactement au même, c'est même plus conseiller au cas ou si on change le type TBlock(ici ce n'est pas spécialement utile, mais imaginez un nombre float, et que vous préferez un double après ^^).

    Pour la surcharge de new, je l'utilise bien, en effet, regardes bien, j'ai fais un define dans le .h

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #define new new(__LINE__, __FILE__)
    #define delete  qgm::Memory::instance().prepareDelete(__LINE__, __FILE__);\
                    delete

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Quand j'avais réalisé un memory manager pour le debug, j'avais aussi réalisé la macro #define new new (__LINE__, __FILE__)et j'avais des erreurs sur les objets delete depuis la std

    Je n'ai jamais vraiment compris l'erreur (include à l'envers ? ... ?), mais comme correction, j'ai modifié mes defines
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #if NDEBUG
    #define MY_HEAP
    #else
    #define MY_HEAP (__LINE__, __FILE__)
    #endif
    puis mes news
    Ne voulant pas me trimballer mon memory manager en release, je m'en étais contenté

    edit:
    en fait de mémoire, c'était le new qui était pas le bon, il utilisait le new de la std, et tentait un delete de chez moi; ou l'inverse.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Membre confirmé
    Inscrit en
    Mars 2006
    Messages
    209
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 209
    Par défaut
    Je n'ai pas vraiment ce problème honnêtement.

    En effet, il m'affiche bien, vous venez de allouer niania, vous venez de désallouez niania.

    Pour mon problème, je l'ai mis sur la sortie cout(étant donner que c'est pour un moteur 3D, ca ne posera pas de problème).

    Merci tout de même de ton aide ^^^.

Discussions similaires

  1. [Débutant] File.Delete impossible, utilisation par process
    Par egautier18 dans le forum C#
    Réponses: 14
    Dernier message: 26/12/2013, 15h07
  2. surcharge de delete : recursive_init_error
    Par apesle dans le forum C++
    Réponses: 3
    Dernier message: 05/02/2009, 14h58
  3. Surcharge de delete
    Par zenux dans le forum C++
    Réponses: 16
    Dernier message: 12/01/2007, 17h43
  4. surcharge operateur delete et héritage
    Par Hervé dans le forum C++
    Réponses: 5
    Dernier message: 29/03/2006, 13h59
  5. [Débutant] Bug 0xC0000005 en utilisant des ofstream
    Par TiKeuj dans le forum SL & STL
    Réponses: 12
    Dernier message: 09/08/2005, 14h14

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