ZenLib

MemoryDebug.h

Go to the documentation of this file.
00001 /*  Copyright (c) MediaArea.net SARL. All Rights Reserved.
00002  *
00003  *  Use of this source code is governed by a zlib-style license that can
00004  *  be found in the License.txt file in the root of the source tree.
00005  */
00006 
00007 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00008 //
00009 // MemoryDebug
00010 //
00011 // Provide "new" and "delete" overloadings to be able to detect memory leaks
00012 // Based on http://loulou.developpez.com/tutoriels/moteur3d/partie1/ 2.2.1
00013 //
00014 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00015 
00016 //---------------------------------------------------------------------------
00017 #ifndef ZenMemoryDebugH
00018 #define ZenMemoryDebugH
00019 //---------------------------------------------------------------------------
00020 
00021 //---------------------------------------------------------------------------
00022 #if defined(ZENLIB_DEBUG)
00023 //---------------------------------------------------------------------------
00024 #include "ZenLib/Conf.h"
00025 #include <fstream>
00026 #include <map>
00027 #include <stack>
00028 #include <string>
00029 //---------------------------------------------------------------------------
00030 
00031 namespace ZenLib
00032 {
00033 
00034 //***************************************************************************
00035 // Class
00036 //***************************************************************************
00037 
00038 class MemoryDebug
00039 {
00040 public :
00041     ~MemoryDebug();
00042     static MemoryDebug& Instance();
00043     static bool g_IsShutdown;
00044     void* Allocate(std::size_t Size, const char* File, int Line, bool Array);
00045     void  Free(void* Ptr, bool Array);
00046     void  NextDelete(const char*, int Line); //Sauvegarde les infos sur la désallocation courante
00047 
00048     void ReportLeaks();
00049 
00050 private :
00051     MemoryDebug();
00052     struct TBlock
00053     {
00054         std::size_t Size;  // Taille allouée
00055         std::string File;  // Fichier contenant l'allocation
00056         int         Line;  // Ligne de l'allocation
00057         bool        Array; // Est-ce un objet ou un tableau ?
00058     };
00059     typedef std::map<void*, TBlock> TBlockMap;
00060 
00061     TBlockMap          m_Blocks;      // Blocs de mémoire alloués
00062     std::stack<TBlock> m_DeleteStack; // Pile dont le sommet contient la ligne et le fichier de la prochaine désallocation
00063 };
00064 
00065 } //NameSpace
00066 
00067 //***************************************************************************
00068 // operator overloadings
00069 //***************************************************************************
00070 
00071 inline void* operator new(std::size_t Size, const char* File, int Line)
00072 {
00073     return ZenLib::MemoryDebug::Instance().Allocate(Size, File, Line, false);
00074 }
00075 inline void* operator new[](std::size_t Size, const char* File, int Line)
00076 {
00077     return ZenLib::MemoryDebug::Instance().Allocate(Size, File, Line, true);
00078 }
00079 
00080 inline void operator delete(void* Ptr)
00081 {
00082     if (ZenLib::MemoryDebug::g_IsShutdown)
00083         free(Ptr);
00084     else
00085         ZenLib::MemoryDebug::Instance().Free(Ptr, false);
00086 }
00087 
00088 inline void operator delete[](void* Ptr)
00089 {
00090     if (ZenLib::MemoryDebug::g_IsShutdown)
00091         free(Ptr);
00092     else
00093         ZenLib::MemoryDebug::Instance().Free(Ptr, true);
00094 }
00095 
00096 #if !defined(__BORLANDC__) // Borland does not support overloaded delete
00097 inline void operator delete(void* Ptr, const char* File, int Line)
00098 {
00099     ZenLib::MemoryDebug::Instance().NextDelete(File, Line);
00100     ZenLib::MemoryDebug::Instance().Free(Ptr, false);
00101 }
00102 
00103 inline void operator delete[](void* Ptr, const char* File, int Line)
00104 {
00105     ZenLib::MemoryDebug::Instance().NextDelete(File, Line);
00106     ZenLib::MemoryDebug::Instance().Free(Ptr, true);
00107 }
00108 #endif
00109 
00110 #if !defined(__MINGW32__) //TODO: Does not work on MinGW, don't know why
00111 #ifndef new
00112     #define new         new(__FILE__, __LINE__)
00113 #endif
00114 #ifndef delete
00115     #define delete      ZenLib::MemoryDebug::Instance().NextDelete(__FILE__, __LINE__), delete
00116 #endif
00117 #endif // __MINGW32__
00118 
00119 #endif // defined(ZENLIB_DEBUG)
00120 
00121 #endif // ZenMemoryDebugH