KeosMemoryManager.cpp

Go to the documentation of this file.
00001 /*
00002  * This source file is part of KEOS (Free 3D Engine)
00003  * For the latest info, see http://www.keosengine.org/
00004  * E-mails : thierry.vouriot@keosengine.org, yeri@keosengine.org
00005  *
00006  * This program is free software; you can redistribute it and/or modify it under
00007  * the terms of the GNU Lesser General Public License as published by the Free Software
00008  * Foundation; either version 2 of the License, or (at your option) any later
00009  * version.
00010  *
00011  * This program is distributed in the hope that it will be useful, but WITHOUT
00012  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00013  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public License along with
00016  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00017  * Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00018  * http://www.gnu.org/copyleft/lesser.txt.
00019  *
00020  */
00021 
00022 //==========================================================
00023 // ORIGINAL COPYRIGHT FOLLOWS
00024 //==========================================================
00025 // Yes::Engine - Free C++ 3D engine
00026 //
00027 // Copyright (C) 2004-2005 Laurent Gomila
00028 //
00029 // This program is free software; you can redistribute it and/or
00030 // modify it under the terms of the GNU General Public License
00031 // as published by the Free Software Foundation; either version 2
00032 // of the License, or (at your option) any later version.
00033 //
00034 // This program is distributed in the hope that it will be useful,
00035 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00036 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00037 // GNU General Public License for more details.
00038 //
00039 // You should have received a copy of the GNU General Public License
00040 // along with this program; if not, write to the Free Software
00041 // Foundation, Inc.,
00042 // 59 Temple Place - Suite 330,
00043 // Boston, MA  02111-1307, USA.
00044 //
00045 // E-mail : laurent.gom@gmail.com
00046 //==========================================================
00047 
00048 #include "KeosMemoryManager.h"
00049 #include "KeosException.h"
00050 #include "KeosNoMemoryMacros.h"
00051 
00052 namespace Keos
00053 {
00054   //=======================================================================
00055   // CMemoryManager implementation
00056   //=======================================================================
00057 
00058   //-----------------------------------------------------------------------
00059   CMemoryManager::CMemoryManager() :
00060       m_File(KEOS_MEMLEAKS_FILE)
00061   {
00062     // The file is open ?
00063     if (!m_File)
00064       throw CLoadingFailed(KEOS_MEMLEAKS_FILE, "Impossible to write in file", "CMemoryManager::CMemoryManager");
00065 
00066     // Write header
00067     m_File << "=============================================" << std::endl;
00068     m_File << " Keos::Engine v" << KEOS_VERSION_MAJOR << "." << KEOS_VERSION_MINOR <<
00069     "." << KEOS_VERSION_PATCH << " - Memory leak tracker - " << std::endl;
00070     m_File << "=============================================" << std::endl << std::endl;
00071 
00072   }
00073 
00074   //-----------------------------------------------------------------------
00075   CMemoryManager::~CMemoryManager()
00076   {
00077     if (m_Blocks.empty())
00078     {
00079       // Aucune fuite
00080       m_File << std::endl;
00081       m_File << "==================" << std::endl;
00082       m_File << " No leak detected " << std::endl;
00083       m_File << "==================" << std::endl;
00084     }
00085     else
00086     {
00087       // Fuites mémoires
00088       m_File << std::endl;
00089       m_File << "===============================" << std::endl;
00090       m_File << " Some leaks have been detected " << std::endl;
00091       m_File << "===============================" << std::endl;
00092       m_File << std::endl;
00093 
00094       ReportLeaks();
00095     }
00096   }
00097 
00098   //-----------------------------------------------------------------------
00099   CMemoryManager& CMemoryManager::Instance()
00100   {
00101     static CMemoryManager sInst;
00102 
00103     return sInst;
00104   }
00105 
00106   //-----------------------------------------------------------------------
00107   void CMemoryManager::ReportLeaks()
00108   {
00109     // Détail des fuites
00110     size_t nTotalSize = 0;
00111     for (TBlockMap::iterator i = m_Blocks.begin(); i != m_Blocks.end(); ++i)
00112     {
00113       // Ajout de la taille du bloc au cumul
00114       nTotalSize += i->second.nSize;
00115 
00116       // Inscription dans le fichier des informations sur le bloc courant
00117       m_File << "-> 0x" << i->first
00118       << " | "   << std::setw(7) << std::setfill(' ') << static_cast<int>(i->second.nSize) << " bytes"
00119       << " | "   << i->second.File.Filename() << " (" << i->second.nLine << ")" << std::endl;
00120 
00121       // Libération de la mémoire
00122       free(i->first);
00123     }
00124 
00125     // Affichage du cumul des fuites
00126     m_File << std::endl << std::endl << "-- "
00127     << static_cast<int>(m_Blocks.size()) << " Blocks not released, "
00128     << static_cast<int>(nTotalSize)       << " bytes --"
00129     << std::endl;
00130   }
00131 
00132   //-----------------------------------------------------------------------
00133   void* CMemoryManager::Allocate(size_t nSize, const CFile& File, int nLine, bool bArray)
00134   {
00135     // Allocation de la mémoire
00136     void* pPtr = malloc(nSize);
00137 
00138     // Ajout du bloc à la liste des blocs alloués
00139     TBlock NewBlock;
00140     NewBlock.nSize  = nSize;
00141     NewBlock.File   = File;
00142     NewBlock.nLine  = nLine;
00143     NewBlock.bArray = bArray;
00144     m_Blocks[pPtr]  = NewBlock;
00145 
00146     // Loggization
00147     m_File << "++ Allocation    | 0x" << pPtr
00148     << " | " << std::setw(7) << std::setfill(' ') << static_cast<int>(NewBlock.nSize) << " bytes"
00149     << " | " << NewBlock.File.Filename() << " (" << NewBlock.nLine << ")" << std::endl;
00150 
00151     return pPtr;
00152   }
00153 
00154   //-----------------------------------------------------------------------
00155   void CMemoryManager::Free(void* pPtr, bool bArray)
00156   {
00157     // Recherche de l'adresse dans les blocs alloués
00158     TBlockMap::iterator It = m_Blocks.find(pPtr);
00159 
00160     // Si le bloc n'a pas été alloué, on génère une erreur
00161     if (It == m_Blocks.end())
00162     {
00163       // En fait ça arrive souvent, du fait que le delete surchargé est pris en compte même là où on n'inclue pas DebugNew.h,
00164       // mais pas la macro pour le new
00165       // Dans ce cas on détruit le bloc et on quitte immédiatement
00166       free(pPtr);
00167       return;
00168     }
00169 
00170     // Si le type d'allocation ne correspond pas, on génère une erreur
00171     if (It->second.bArray != bArray)
00172     {
00173       throw CBadDelete(pPtr, It->second.File.Filename(), It->second.nLine, !bArray);
00174     }
00175 
00176     // Finalement, si tout va bien, on supprime le bloc et on loggiz tout ça
00177     m_File << "-- Deallocation  | 0x" << pPtr
00178     << " | " << std::setw(7) << std::setfill(' ') << static_cast<int>(It->second.nSize) << " bytes"
00179     << " | " << m_DeleteStack.top().File.Filename() << " (" << m_DeleteStack.top().nLine << ")" << std::endl;
00180     m_Blocks.erase(It);
00181     m_DeleteStack.pop();
00182 
00183     // Libération de la mémoire
00184     free(pPtr);
00185   }
00186 
00187   //-----------------------------------------------------------------------
00188   void CMemoryManager::NextDelete(const CFile& File, int nLine)
00189   {
00190     TBlock Delete;
00191     Delete.File = File;
00192     Delete.nLine = nLine;
00193 
00194     m_DeleteStack.push(Delete);
00195   }
00196 
00197 } // namespace Keos

Generated on Fri Mar 9 14:29:02 2007 for Keos by  doxygen 1.5.1-p1