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 <sstream>
00027 #include <memory>
00028 #include <map>
00029 #include <stack>
00030 #include <string>
00031 //---------------------------------------------------------------------------
00032 
00033 namespace ZenLib
00034 {
00035 
00036 //***************************************************************************
00037 // Class
00038 //***************************************************************************
00039 
00040 class MemoryDebug
00041 {
00042 public :
00043     ~MemoryDebug();
00044     static MemoryDebug& Instance();
00045     static bool g_IsShutdown;
00046     void* Allocate(std::size_t Size, const char* File, int Line, bool Array);
00047     void  Free(void* Ptr, bool Array);
00048     void  NextDelete(const char*, int Line); //Sauvegarde les infos sur la désallocation courante
00049 
00050     void ReportLeaks();
00051 
00052 private :
00053     MemoryDebug();
00054     struct TBlock
00055     {
00056         std::size_t Size;  // Taille allouée
00057         std::string File;  // Fichier contenant l'allocation
00058         int         Line;  // Ligne de l'allocation
00059         bool        Array; // Est-ce un objet ou un tableau ?
00060     };
00061     typedef std::map<void*, TBlock> TBlockMap;
00062 
00063     TBlockMap          m_Blocks;      // Blocs de mémoire alloués
00064     std::stack<TBlock> m_DeleteStack; // Pile dont le sommet contient la ligne et le fichier de la prochaine désallocation
00065 };
00066 
00067 } //NameSpace
00068 
00069 //***************************************************************************
00070 // operator overloadings
00071 //***************************************************************************
00072 
00073 inline void* operator new(std::size_t Size, const char* File, int Line)
00074 {
00075     return ZenLib::MemoryDebug::Instance().Allocate(Size, File, Line, false);
00076 }
00077 inline void* operator new[](std::size_t Size, const char* File, int Line)
00078 {
00079     return ZenLib::MemoryDebug::Instance().Allocate(Size, File, Line, true);
00080 }
00081 
00082 inline void operator delete(void* Ptr)
00083 {
00084     if (ZenLib::MemoryDebug::g_IsShutdown)
00085         free(Ptr);
00086     else
00087         ZenLib::MemoryDebug::Instance().Free(Ptr, false);
00088 }
00089 
00090 inline void operator delete[](void* Ptr)
00091 {
00092     if (ZenLib::MemoryDebug::g_IsShutdown)
00093         free(Ptr);
00094     else
00095         ZenLib::MemoryDebug::Instance().Free(Ptr, true);
00096 }
00097 
00098 #if !defined(__BORLANDC__) // Borland does not support overloaded delete
00099 inline void operator delete(void* Ptr, const char* File, int Line)
00100 {
00101     ZenLib::MemoryDebug::Instance().NextDelete(File, Line);
00102     ZenLib::MemoryDebug::Instance().Free(Ptr, false);
00103 }
00104 
00105 inline void operator delete[](void* Ptr, const char* File, int Line)
00106 {
00107     ZenLib::MemoryDebug::Instance().NextDelete(File, Line);
00108     ZenLib::MemoryDebug::Instance().Free(Ptr, true);
00109 }
00110 #endif
00111 
00112 #if !defined(__MINGW32__) //TODO: Does not work on MinGW, don't know why
00113 #ifndef new
00114     #define new         new(__FILE__, __LINE__)
00115 #endif
00116 #ifndef delete
00117     #define delete      ZenLib::MemoryDebug::Instance().NextDelete(__FILE__, __LINE__), delete
00118 #endif
00119 #endif // __MINGW32__
00120 
00121 #endif // defined(ZENLIB_DEBUG)
00122 
00123 #endif // ZenMemoryDebugH