1 /*  Copyright (c) MediaArea.net SARL. All Rights Reserved.
2  *
3  *  Use of this source code is governed by a zlib-style license that can
4  *  be found in the License.txt file in the root of the source tree.
5  */
6 
7 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8 //
9 // MemoryDebug
10 //
11 // Provide "new" and "delete" overloadings to be able to detect memory leaks
12 // Based on http://loulou.developpez.com/tutoriels/moteur3d/partie1/ 2.2.1
13 //
14 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
15 
16 //---------------------------------------------------------------------------
17 #ifndef ZenMemoryDebugH
18 #define ZenMemoryDebugH
19 //---------------------------------------------------------------------------
20 
21 //---------------------------------------------------------------------------
22 #if defined(ZENLIB_DEBUG)
23 //---------------------------------------------------------------------------
24 #include "ZenLib/Conf.h"
25 #include <fstream>
26 #include <sstream>
27 #include <memory>
28 #include <map>
29 #include <stack>
30 #include <string>
31 //---------------------------------------------------------------------------
32 
33 namespace ZenLib
34 {
35 
36 //***************************************************************************
37 // Class
38 //***************************************************************************
39 
40 class MemoryDebug
41 {
42 public :
43     ~MemoryDebug();
44     static MemoryDebug& Instance();
45     static bool g_IsShutdown;
46     void* Allocate(std::size_t Size, const char* File, int Line, bool Array);
47     void  Free(void* Ptr, bool Array);
48     void  NextDelete(const char*, int Line); //Sauvegarde les infos sur la d�sallocation courante
49 
50     void ReportLeaks();
51 
52 private :
53     MemoryDebug();
54     struct TBlock
55     {
56         std::size_t Size;  // Taille allou�e
57         std::string File;  // Fichier contenant l'allocation
58         int         Line;  // Ligne de l'allocation
59         bool        Array; // Est-ce un objet ou un tableau ?
60     };
61     typedef std::map<void*, TBlock> TBlockMap;
62 
63     TBlockMap          m_Blocks;      // Blocs de m�moire allou�s
64     std::stack<TBlock> m_DeleteStack; // Pile dont le sommet contient la ligne et le fichier de la prochaine d�sallocation
65 };
66 
67 } //NameSpace
68 
69 //***************************************************************************
70 // operator overloadings
71 //***************************************************************************
72 
new(std::size_t Size,const char * File,int Line)73 inline void* operator new(std::size_t Size, const char* File, int Line)
74 {
75     return ZenLib::MemoryDebug::Instance().Allocate(Size, File, Line, false);
76 }
77 inline void* operator new[](std::size_t Size, const char* File, int Line)
78 {
79     return ZenLib::MemoryDebug::Instance().Allocate(Size, File, Line, true);
80 }
81 
delete(void * Ptr)82 inline void operator delete(void* Ptr)
83 {
84     if (ZenLib::MemoryDebug::g_IsShutdown)
85         free(Ptr);
86     else
87         ZenLib::MemoryDebug::Instance().Free(Ptr, false);
88 }
89 
90 inline void operator delete[](void* Ptr)
91 {
92     if (ZenLib::MemoryDebug::g_IsShutdown)
93         free(Ptr);
94     else
95         ZenLib::MemoryDebug::Instance().Free(Ptr, true);
96 }
97 
98 #if !defined(__BORLANDC__) // Borland does not support overloaded delete
delete(void * Ptr,const char * File,int Line)99 inline void operator delete(void* Ptr, const char* File, int Line)
100 {
101     ZenLib::MemoryDebug::Instance().NextDelete(File, Line);
102     ZenLib::MemoryDebug::Instance().Free(Ptr, false);
103 }
104 
105 inline void operator delete[](void* Ptr, const char* File, int Line)
106 {
107     ZenLib::MemoryDebug::Instance().NextDelete(File, Line);
108     ZenLib::MemoryDebug::Instance().Free(Ptr, true);
109 }
110 #endif
111 
112 #if !defined(__MINGW32__) //TODO: Does not work on MinGW, don't know why
113 #ifndef new
114     #define new         new(__FILE__, __LINE__)
115 #endif
116 #ifndef delete
117     #define delete      ZenLib::MemoryDebug::Instance().NextDelete(__FILE__, __LINE__), delete
118 #endif
119 #endif // __MINGW32__
120 
121 #endif // defined(ZENLIB_DEBUG)
122 
123 #endif // ZenMemoryDebugH
124