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 :

Empêcher la bibliothèque standard MSVC d'utiliser la surcharge delete


Sujet :

Langage C++

  1. #1
    Membre du Club Avatar de Nanos
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 109
    Points : 50
    Points
    50
    Par défaut Empêcher la bibliothèque standard MSVC d'utiliser la surcharge delete
    Bonjour à tous,

    Aujourd'hui, je viens vous voir en réclamant votre aide après de longs jours à résoudre un problème qui me prend énormément la tête.
    Je pourrais faire comme j'ai fait jusqu'à aujourd'hui, c'est-à-dire de résoudre mes problèmes par moi-même mais sur un mois de projet, je n'ai que 6 minables fichiers sources qui m'ont posés une bonne dizaines de problèmes. Ces problèmes se passant uniquement à la fin d'éxecution du programme, les debuggers ne m'aident pas.

    Donc voici mon problème :

    Je reprend le principe du détecteur de fuite de mémoire élaboré par loulou. Merci à lui.

    Je surcharge donc dans mon programme les operator new, new[], delete et delete[]. Cependant quand je compiles avec MSVC mon operator delete est appelé plusieurs fois alors que je le demande pas.
    Du côté de GCC, mon programme, apparement appelle une fois l'operateur delete.

    Je me disais qu'éventuellement, le prototype de ma surcharge pourrait poser problème dans le cas où la librarie standard se retrouve à l'utiliser. Je suis donc venu à commenter la ligne 76 de MemLeakTracker.cpp et j'ai remarqué que ça fonctionne. Il y a donc un problème au niveau de la libération de mémoire venant d'un bloc de la bibliothèque standard. Donc comment faire en sorte que la bibliothèque standard n'utilise pas ma surcharge delete ?

    Car même si j'arrive à libérer la mémoire allouée par la bibliothèque standard, celle-ci est censé avec ma surcharge delete demande de recréer une instance de MemLeakTracker qui a été précédement détruit parce que c'est la fin du programme... Mais si j'affiche à quelque chose dans la console lors de la création d'une instance de MemLeakTracker, je me rend compte qu'une seule instance est bien créer. Donc la bibliothèque standard utilise mon operator delete surchargé qui appelle une fonction qui n'existe pas mais qui est quand même exécuté. (c.f. sortie MSVC) Je suis perdu...

    EDIT : J'ai remarqué que j'ai le même problème quand j'utilise uniquement le MemoryManager de loulou. MSVC, tu me fais vraiment c****...

    Voici mes sources :

    • MemLeakTracker.h
      Code cpp : 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
      #ifndef MEM_LEAK_TRACKER__H
      #define MEM_LEAK_TRACKER__H
       
      #include <map>
      #include <iostream>
      #include <cstdlib>
       
      struct MemBlock
      {
      	const char* file;
      	unsigned short int line;
      	size_t size;
      };
       
      class MemLeakTracker
      {
      public:
          static MemLeakTracker& getInstance();
      	void* const allocate(const char* const file, unsigned short int const line,
      		                 size_t const size);
      	void deallocate(void* pointer);
       
      private:
          MemLeakTracker();
      	~MemLeakTracker();
       
      	std::map<void*, MemBlock> m_blocks;
      	std::map<void*, MemBlock>::iterator m_it;
      };
       
      void* operator new(size_t const size, const char* const file,
                         unsigned short int const line);
       
      void* operator new[](size_t const size, const char* const file,
                           unsigned short int const line);
       
      void operator delete(void* pointer) throw();
       
      void operator delete[](void* pointer) throw();
       
      #endif //MEM_LEAK_TRACKER__H
       
      #define new new(__FILE__, __LINE__)
      #define free delete
    • MemLeakTracker.cpp
      Code cpp : 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
      #include <sstream>
      #include "GameEngine/Common/Debug/MemLeakTracker.h"
      #include "GameEngine/Common/Debug/MemLeakTrackerOff.h"
       
      MemLeakTracker::MemLeakTracker()
      {
      	std::cout << "Creation instance MemLeakTracker" << std::endl;
      }
       
      MemLeakTracker::~MemLeakTracker()
      {
      	if(!m_blocks.empty())
      	{
      		unsigned long long totalSize = 0;
      		size_t size;
      		std::wcout << m_blocks.size() << " memory leaks detected !\n";
       
      		for(m_it = m_blocks.begin(); m_it != m_blocks.end(); m_it++)
      		{
      			std::wcout << "    At 0x" << m_it->first << " in " <<
      			m_it->second.file << " at line " << m_it->second.line << " (";
      			size = m_it->second.size;
      			std::wcout << size << "B)\n";
      			totalSize += size;
       
      			free(m_it->first); //Crash with MSVC if I let this line
      		}
       
      		std::wcout << totalSize << "B has been freed !\n";
      	}
      }
       
      MemLeakTracker& MemLeakTracker::getInstance()
      {
          static MemLeakTracker instance;
          return instance;
      }
       
      void* const MemLeakTracker::allocate(const char* const file,
                                            unsigned short int const line,
                                            size_t const size)
      {
      	void* const pointer = malloc(size);
      	MemBlock myBlock;
       
      	myBlock.file = file;
      	myBlock.line = line;
      	myBlock.size = size;
       
      	m_blocks[pointer] = myBlock;
       
      	return pointer;
      }
       
      void MemLeakTracker::deallocate(void* pointer)
      {
      	m_it = m_blocks.find(pointer);
      	if(m_it == m_blocks.end()) //If the pointer is not in the memory block stack
      	{
      		std::wcout << "Trying to delete " << pointer <<
      			" which is not in the stack" << std::endl;
      		//free(pointer);
      		std::wcout << "Success" << std::endl;
      	}
      	else
      	{
      		std::wcout << "Trying to delete " << pointer << std::endl;
      		m_blocks.erase(pointer);
      		free(pointer);
      		std::wcout << "Success to delete " << pointer << std::endl;
      	}
      }
       
      void* operator new(size_t const size, const char* const file,
                         unsigned short int const line)
      {
          return MemLeakTracker::getInstance().allocate(file, line, size);
      }
       
      void* operator new[](size_t const size, const char* const file,
                           unsigned short int const line)
      {
          return MemLeakTracker::getInstance().allocate(file, line, size);
      }
       
      void operator delete(void* pointer) throw()
      {
          MemLeakTracker::getInstance().deallocate(pointer);
      }
       
      void operator delete[](void* pointer) throw()
      {
          MemLeakTracker::getInstance().deallocate(pointer);
      }
    • MemLeakTrackerOff.h
      Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      #undef new
      #undef free
    • main.cpp
      Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      #include <iostream>
      #include "GameEngine/Common/Debug/MemLeakTracker.h"
       
      int main()
      {
      	char* a = new char;
       
      	return 0;
      }


    Et les sorties :

    • Avec MSVC :
      Citation Envoyé par console
      Creation instance MemLeakTracker
      1 memory leaks detected !
      At 0x000000000031F950 in ..\..\..\examples\01\src\main.cpp at line 6 (1B)
      1B has been freed !
      Trying to delete 00000000003246F0 which is not in the stack
      Success
      Trying to delete 0000000000323FD0 which is not in the stack
      Success
      Trying to delete 0000000000325FF0 which is not in the stack
      Success
      Press any key to continue . . .
      CRASH

    • Avec GCC :
      Citation Envoyé par console
      Creation instance MemLeakTracker
      1 memory leaks detected !
      At 0x0x632fd8 in D:\saggah\Projets\GameEngine\examples\01\src\main.cpp at line 6 (1B)
      1B has been freed !
      Trying to delete 0x630f40 which is not in the stack
      Success
      SUCCESSFULL


    Quelqu'un peut m'aider S.V.P. ?

    Et aussi j'ai une question qui n'a pas grand chose à avoir mais je vais quand même la poser. Quand on compile un programme avec une bibliothèque directement (donc pas linkage statique ni dynamique), pourquoi le programme, une fois compilé en Debug et même Release (avec aussi des optimizations de taille) inclu même les fonctions non utilisés. Pourquoi n'y a t-il pas d'optimisation de la part des compilateurs pour ça ?

    Je m'explique, que je compile en mode Debug ou mode Release (et même avec les optimisations de taille) et que j'inclu comme ça au hasard des fichiers headers que j'utilise même pas, pourquoi le compilateur garde ces fichiers dans mon binaire ? Car je trouve ça assez étrange vu la complexité des compilateurs, qu'une telle fonctionnalitée n'existe pas.

    Bonne journée et merci d'avance.

  2. #2
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Bonjour,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #define new new(__FILE__, __LINE__)
    #define free delete
    C'est une très mauvaise idée .

  3. #3
    Membre chevronné Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 043
    Points : 2 234
    Points
    2 234
    Par défaut
    Je ne vois pas le problème avec le define du new mais par contre le free....
    Si tu define delete appelle le delete ou DELETE ou un autre truc qui ressemble a delete et pas a une autre fonction qui est free. http://www.cplusplus.com/reference/cstdlib/free/
    Homer J. Simpson


  4. #4
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par Astraya Voir le message
    Je ne vois pas le problème avec le define du new
    Code monHeader.h : Sélectionner tout - Visualiser dans une fenêtre à part
    #define new new(machin)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #include "monHeader.h"
    #include <algorithm>
     
    void newCreatedType(void);
    Code algorithm : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void newFunction(void)
    {
     
    }
     
    void operator new(...)
    {
     
    }

    Voilà un exemple

  5. #5
    Membre chevronné Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 043
    Points : 2 234
    Points
    2 234
    Par défaut
    Ah oui autant pour moi j'avais pas vu que le nom était le même :p
    La clim n'est pas assez forte au boulot :p
    Homer J. Simpson


  6. #6
    Membre du Club Avatar de Nanos
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 109
    Points : 50
    Points
    50
    Par défaut
    Tout d'abord merci pour vos réponses.

    Si j'ai bien compris le problème est que je surcharge l'opérateur new après d'avoir fait une #define new new(...). Je comprend que ça pose problème, mais ça ne devrait pas se poser lors de la compilation pour syntaxe foireuse ?

    Et aussi dans mon MemLeakTracker.cpp avec l'aide de MemLeakTrackerOff.h, juste après l'inclusion de ce premier, je "supprime" la #define new. Donc le problème n'est pas censé avoir lieu, non ?

    Je précise que j'ai viré la #define free delete et le même problème est présent. Parce que je suppose le problème là est qu'un bloc alloué avec malloc() est liberé avec delete ?

    Je pense avoir mal compris les problèmes...

  7. #7
    Membre chevronné Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 043
    Points : 2 234
    Points
    2 234
    Homer J. Simpson


  8. #8
    Membre du Club Avatar de Nanos
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 109
    Points : 50
    Points
    50
    Par défaut
    Non, je suis désolé je ne vois pas le soucis. Après j'ai amélioré un peu le code en mettant les surcharges inline et en rajoutant les surcharges delete et delete[] en cas d'échec avec new et new[].

    J'ai essayé en reprenant le code de loulou a 100% (DebugNew, DebugNewOff, MemoryManager.cpp et MemoryManager.h et j'ai aussi un crash exactement sur la même ligne que la mienne, c'est-à-dire, dans son code, à la ligne 162. Ici, à la ligne 12 :
    Code cpp : 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
    void CMemoryManager::Free(void* Ptr, bool Array)
    {
        // Recherche de l'adresse dans les blocs alloués
        TBlockMap::iterator It = m_Blocks.find(Ptr);
     
        // Si le bloc n'a pas été alloué, on génère une erreur
        if (It == m_Blocks.end())
        {
            // En fait ça arrive souvent, du fait que le delete surchargé est pris en compte même là où on n'inclue pas DebugNew.h,
            // mais pas la macro pour le new
            // Dans ce cas on détruit le bloc et on quitte immédiatement
            free(Ptr);
            return;
        }
     
        // Si le type d'allocation ne correspond pas, on génère une erreur
        if (It->second.Array != Array)
        {
            throw CBadDelete(Ptr, It->second.File.Filename(), It->second.Line, !Array);
        }
     
        // Finalement, si tout va bien, on supprime le bloc et on loggiz tout ça
        m_File << "-- Désallocation | 0x" << Ptr
               << " | " << std::setw(7) << std::setfill(' ') << static_cast<int>(It->second.Size) << " octets"
               << " | " << m_DeleteStack.top().File.Filename() << " (" << m_DeleteStack.top().Line << ")" << std::endl;
        m_Blocks.erase(It);
        m_DeleteStack.pop();
     
        // Libération de la mémoire
        free(Ptr);
    }
    Si je commente cette ligne, le programme ne plante pas.

    Je pense que je ne vais pas libérer les blocs de mémoire qui ne sont pas dans ma pile, uniquement avec MSVC. A pars si vous avez une solution miracle ?

    Je laisse quand même le sujet non résolu pendant quelques temps, dans le doute...

    Merci quand même de votre aide...

    Bonne journée.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 20
    Dernier message: 18/09/2012, 20h40
  2. Windows utilise-t-il la bibliothèque standard du C ?
    Par baccali dans le forum Windows
    Réponses: 24
    Dernier message: 16/02/2012, 10h21
  3. Réponses: 2
    Dernier message: 19/09/2007, 17h37
  4. Réponses: 2
    Dernier message: 19/12/2006, 12h45
  5. Le type Arbre binaire dans les bibliothèques standards ?
    Par sam69 dans le forum API standards et tierces
    Réponses: 6
    Dernier message: 10/05/2006, 13h50

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