ZenLib
MemoryDebug.h
Go to the documentation of this file.
00001 // ZenLib::MemoryDebug - To debug memory leaks
00002 // Copyright (C) 2002-2011 MediaArea.net SARL, Info@MediaArea.net
00003 //
00004 // This software is provided 'as-is', without any express or implied
00005 // warranty.  In no event will the authors be held liable for any damages
00006 // arising from the use of this software.
00007 //
00008 // Permission is granted to anyone to use this software for any purpose,
00009 // including commercial applications, and to alter it and redistribute it
00010 // freely, subject to the following restrictions:
00011 //
00012 // 1. The origin of this software must not be misrepresented; you must not
00013 //    claim that you wrote the original software. If you use this software
00014 //    in a product, an acknowledgment in the product documentation would be
00015 //    appreciated but is not required.
00016 // 2. Altered source versions must be plainly marked as such, and must not be
00017 //    misrepresented as being the original software.
00018 // 3. This notice may not be removed or altered from any source distribution.
00019 //
00020 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00021 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00022 // MemoryDebug
00023 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00024 //
00025 // Provide "new" and "delete" overloadings to be able to detect memory leaks
00026 // Based on http://loulou.developpez.com/tutoriels/moteur3d/partie1/ 2.2.1
00027 //
00028 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00029 
00030 //---------------------------------------------------------------------------
00031 #ifndef ZenMemoryDebugH
00032 #define ZenMemoryDebugH
00033 //---------------------------------------------------------------------------
00034 
00035 //---------------------------------------------------------------------------
00036 #if defined(ZENLIB_DEBUG)
00037 //---------------------------------------------------------------------------
00038 #include "ZenLib/Conf.h"
00039 #include <fstream>
00040 #include <map>
00041 #include <stack>
00042 #include <string>
00043 //---------------------------------------------------------------------------
00044 
00045 namespace ZenLib
00046 {
00047 
00048 //***************************************************************************
00049 // Class
00050 //***************************************************************************
00051 
00052 class MemoryDebug
00053 {
00054 public :
00055     ~MemoryDebug();
00056     static MemoryDebug& Instance();
00057 
00058     void* Allocate(std::size_t Size, const char* File, int Line, bool Array);
00059     void  Free(void* Ptr, bool Array);
00060     void  NextDelete(const char*, int Line); //Sauvegarde les infos sur la désallocation courante
00061 
00062 private :
00063     MemoryDebug();
00064     void ReportLeaks();
00065     struct TBlock
00066     {
00067         std::size_t Size;  // Taille allouée
00068         std::string File;  // Fichier contenant l'allocation
00069         int         Line;  // Ligne de l'allocation
00070         bool        Array; // Est-ce un objet ou un tableau ?
00071     };
00072     typedef std::map<void*, TBlock> TBlockMap;
00073 
00074     TBlockMap          m_Blocks;      // Blocs de mémoire alloués
00075     std::stack<TBlock> m_DeleteStack; // Pile dont le sommet contient la ligne et le fichier de la prochaine désallocation
00076 };
00077 
00078 } //NameSpace
00079 
00080 //***************************************************************************
00081 // operator overloadings
00082 //***************************************************************************
00083 
00084 inline void* operator new(std::size_t Size, const char* File, int Line)
00085 {
00086     return ZenLib::MemoryDebug::Instance().Allocate(Size, File, Line, false);
00087 }
00088 inline void* operator new[](std::size_t Size, const char* File, int Line)
00089 {
00090     return ZenLib::MemoryDebug::Instance().Allocate(Size, File, Line, true);
00091 }
00092 
00093 inline void operator delete(void* Ptr)
00094 {
00095     ZenLib::MemoryDebug::Instance().Free(Ptr, false);
00096 }
00097 
00098 inline void operator delete[](void* Ptr)
00099 {
00100     ZenLib::MemoryDebug::Instance().Free(Ptr, true);
00101 }
00102 
00103 #if !defined(__BORLANDC__) // Borland does not support overloaded delete
00104 inline void operator delete(void* Ptr, const char* File, int Line)
00105 {
00106     ZenLib::MemoryDebug::Instance().NextDelete(File, Line);
00107     ZenLib::MemoryDebug::Instance().Free(Ptr, false);
00108 }
00109 
00110 inline void operator delete[](void* Ptr, const char* File, int Line)
00111 {
00112     ZenLib::MemoryDebug::Instance().NextDelete(File, Line);
00113     ZenLib::MemoryDebug::Instance().Free(Ptr, true);
00114 }
00115 #endif
00116 
00117 #if !defined(__MINGW32__) //TODO: Does not work on MinGW, don't know why
00118 #ifndef new
00119     #define new         new(__FILE__, __LINE__)
00120 #endif
00121 #ifndef delete
00122     #define delete      ZenLib::MemoryDebug::Instance().NextDelete(__FILE__, __LINE__), delete
00123 #endif
00124 #endif // __MINGW32__
00125 
00126 #endif // defined(ZENLIB_DEBUG)
00127 
00128 #endif // ZenMemoryDebugH
00129 
00130