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 #include "ZenLib/PreComp.h"
9 #ifdef __BORLANDC__
10     #pragma hdrstop
11 #endif
12 //---------------------------------------------------------------------------
13 
14 //---------------------------------------------------------------------------
15 #include "ZenLib/Conf_Internal.h"
16 //---------------------------------------------------------------------------
17 
18 //---------------------------------------------------------------------------
19 #if defined(ZENLIB_DEBUG)
20 //---------------------------------------------------------------------------
21 #include <iomanip>
22 #include <sstream>
23 #include "ZenLib/MemoryDebug.h"
24 #include "ZenLib/Ztring.h"
25 #ifdef WINDOWS
26     #include <io.h>
27 #else
28     #include <cstdio>
29 #endif
30 #include <fcntl.h>
31 #include <sys/stat.h>
32 using namespace std;
33 //---------------------------------------------------------------------------
34 
35 namespace ZenLib
36 {
37 
38 bool MemoryDebug::g_IsShutdown = false;
39 //***************************************************************************
40 // Constructors/destructor
41 //***************************************************************************
42 
MemoryDebug()43 MemoryDebug::MemoryDebug()
44 {
45 }
46 
~MemoryDebug()47 MemoryDebug::~MemoryDebug()
48 {
49     if (!m_Blocks.empty())
50         ReportLeaks();
51     g_IsShutdown = true;
52 }
53 
54 //***************************************************************************
55 // Instance
56 //***************************************************************************
57 
Instance()58 MemoryDebug& MemoryDebug::Instance()
59 {
60     static MemoryDebug Inst;
61     return Inst;
62 }
63 
64 //***************************************************************************
65 // Reports
66 //***************************************************************************
67 
ReportLeaks()68 void MemoryDebug::ReportLeaks()
69 {
70     Ztring m_File;
71     //std::ofstream      m_File ("Debug_MemoryLeak.txt");        // Fichier de sortie
72 
73     // D�tail des fuites
74     std::size_t TotalSize = 0;
75     for (TBlockMap::iterator i = m_Blocks.begin(); i != m_Blocks.end(); ++i)
76     {
77         // Ajout de la taille du bloc au cumul
78         TotalSize += i->second.Size;
79 
80         // Inscription dans le fichier des informations sur le bloc courant
81         /*
82         m_File << "-> 0x" << std::hex << i->first << std::dec
83                << " | "   << std::setw(7) << std::setfill(' ') << static_cast<int>(i->second.Size) << " bytes"
84                << " | "   << i->second.File.c_str() << " (" << i->second.Line << ")" << std::endl;
85         */
86         m_File.append(__T("-> 0x"));
87         m_File.append(Ztring::ToZtring((size_t)i->first, 16));
88         m_File.append(__T(" | "));
89         Ztring Temp;
90         Temp.From_Number(static_cast<int>(i->second.Size));
91         while(Temp.size()<7)
92             Temp=__T(" ")+Temp;
93         m_File.append(Temp);
94         m_File.append(__T(" bytes"));
95         m_File.append(__T(" | "));
96         m_File.append(Ztring().From_Local(i->second.File.c_str()));
97         m_File.append(__T(" ("));
98         m_File.append(Ztring::ToZtring(i->second.Line));
99         m_File.append(__T(")"));
100         m_File.append(EOL);
101     }
102 
103     // Affichage du cumul des fuites
104     /*
105     m_File << std::endl << std::endl << "-- "
106            << static_cast<int>(m_Blocks.size()) << " non-released blocs, "
107            << static_cast<int>(TotalSize)       << " bytes --"
108            << std::endl;
109     */
110     m_File.append(EOL);
111     m_File.append(EOL);
112     m_File.append(__T("-- "));
113     m_File.append(Ztring::ToZtring(static_cast<int>(m_Blocks.size())));
114     m_File.append(__T(" non-released blocs, "));
115     m_File.append(Ztring::ToZtring(static_cast<int>(TotalSize)));
116     m_File.append(__T(" bytes --"));
117     m_File.append(EOL);
118 
119     std::string ToWrite=m_File.To_Local().c_str();
120     int m_File_sav=open("Debug_MemoryLeak.txt", O_BINARY|O_RDWR  |O_CREAT);        // Fichier de sortie
121     write(m_File_sav, (int8u*)ToWrite.c_str(), ToWrite.size());
122     close(m_File_sav);
123 }
124 
125 //***************************************************************************
126 // Memory management
127 //***************************************************************************
128 
Allocate(std::size_t Size,const char * File,int Line,bool Array)129 void* MemoryDebug::Allocate(std::size_t Size, const char* File, int Line, bool Array)
130 {
131     // Allocation de la m�moire
132     void* Ptr = malloc(Size);
133 
134     // Ajout du bloc � la liste des blocs allou�s
135     TBlock NewBlock;
136     NewBlock.Size  = Size;
137     NewBlock.File  = File;
138     NewBlock.Line  = Line;
139     NewBlock.Array = Array;
140     m_Blocks[Ptr]  = NewBlock;
141     return Ptr;
142 }
143 
Free(void * Ptr,bool Array)144 void MemoryDebug::Free(void* Ptr, bool Array)
145 {
146     // Recherche de l'adresse dans les blocs allou�s
147     TBlockMap::iterator It = m_Blocks.find(Ptr);
148 
149     // Si le bloc n'a pas �t� allou�, on g�n�re une erreur
150     if (It == m_Blocks.end())
151     {
152         // En fait �a arrive souvent, du fait que le delete surcharge est pris en compte meme la ou on n'inclue pas DebugNew.h,
153         // mais pas la macro pour le new
154         // Dans ce cas on d�truit le bloc et on quitte imm�diatement
155         free(Ptr);
156         return;
157     }
158 
159     // Si le type d'allocation ne correspond pas, on g�n�re une erreur
160     if (It->second.Array != Array)
161     {
162         //throw CBadDelete(Ptr, It->second.File.c_str(), It->second.Line, !Array);
163     }
164 
165     // Finalement, si tout va bien, on supprime le bloc et on loggiz tout �a
166     m_Blocks.erase(It);
167     m_DeleteStack.pop();
168 
169     // Lib�ration de la m�moire
170     free(Ptr);
171 }
172 
NextDelete(const char * File,int Line)173 void MemoryDebug::NextDelete(const char* File, int Line)
174 {
175     TBlock Delete;
176     Delete.File = File;
177     Delete.Line = Line;
178 
179     m_DeleteStack.push(Delete);
180 }
181 
182 //***************************************************************************
183 //
184 //***************************************************************************
185 
186 } //NameSpace
187 
188 #endif // defined(ZENLIB_DEBUG)
189