parent nodes: CPlusPlusApuntesC
Fugas de memoria
Memory Leaks
Author: César TM
Date: Nov/2009
Detectar fugas de memoria
http://msdn.microsoft.com/en-us/library/aa293901(VS.60).aspx
Nota creada: 12 de julio de 2007
Modificada por última vez el 26 de marzo de 2008 por cesartm@gmail.com
26/03/08
Detecting a Memory Leak
The following instructions and example show you how to detect a memory leak.
To detect a memory leak
Create a CMemoryState object and call the Checkpoint member function to get the initial snapshot of memory.
After you perform the memory allocation and deallocation operations, create another CMemoryState object and call Checkpoint for that object to get a current snapshot of memory usage.
Create a third CMemoryState object, call the Difference member function, and supply the previous two CMemoryState objects as arguments. The return value for the Difference function will be nonzero if there is any difference between the two specified memory states, indicating that some memory blocks have not been deallocated.
The following example shows how to check for memory leaks:
// Declare the variables needed
#ifdef _DEBUGCMemoryState oldMemState, newMemState, diffMemState;
oldMemState.Checkpoint();
#endif
// do your memory allocations and deallocations...
CString s = "This is a frame variable";
// the next object is a heap object
CPerson* p = new CPerson( "Smith", "Alan", "581-0215" );
#ifdef _DEBUGnewMemState.Checkpoint();
if( diffMemState.Difference( oldMemState, newMemState ) )
{TRACE( "Memory leaked!n" );
}
#endif
Notice that the memory-checking statements are bracketed by #ifdef _DEBUG / #endif blocks so that they are compiled only in Win32 Debug versions of your program.
A sample report looks like this:
0 bytes in 0 Free Blocks8 bytes in 2 Object Blocks0 bytes in 0 Non-Object BlocksLargest number used: 8 bytesTotal allocations: 8 bytes
The first line describes the number of blocks whose deallocation was delayed if afxMemDF was set to delayFreeMemDF. For more information, see afxMemDF, in the “Macros and Globals” section.
The second line describes how many object blocks still remain allocated on the heap.
The third line describes how many nonobject blocks (arrays or structures allocated with new) were allocated on the heap and not deallocated.
The fourth line gives the maximum memory used by your program at any one time.
The last line lists the total amount of memory used by your program.
Yo lo he hecho de esta forma:
Al principio del archivo .CPP pongo en dos líneas
#define CHECK_FOR_MEMORY_LEAKS_BEGIN CMemoryState oldMemState, newMemState, diffMemState; oldMemState.Checkpoint(); {
#define CHECK_FOR_MEMORY_LEAKS_END } newMemState.Checkpoint(); if( diffMemState.Difference( oldMemState, newMemState ) ) { AfxMessageBox( "Memory leaked!n" ); diffMemState.DumpStatistics(); }
Después, justo antes del código a examinar:#ifdef _DEBUGCHECK_FOR_MEMORY_LEAKS_BEGIN
#endif
Y al acabar el código a examinar:#ifdef _DEBUGCHECK_FOR_MEMORY_LEAKS_END // aquí hay que poner un breakpoint
#endif
La pareja BEGIN END forma un bloque fuera del cual no se tendrá acceso a las variables allí definidas, hay que tener eso en cuenta para que no pete a la hora de compilar en debug.
Queries y Recordsets
todo.low: Confirmar que esto pasa para objetos de C++ y no sólo para objetos de Informática Notarial.
Si intentamos aprovechar una consulta/un recordset para varios usos, preguntando si está abierto y, en ese caso, cerrándolo. Nos irá perdiendo memoria.
void
CParam2ListadosSinSedes::MontarRecordset( BOOL usaDefaultSede /*=TRUE*/ )
{
if( m_query->IsOpen() == TRUE )
m_query->Close(); // ***** POSSIBLE MEMORY LEAK ********
m_sql = _T( "PARAMETERS PARCLASE Long;SELECT PARAM2_LISTADOS.ID_PARAM2_LISTADOS, PARAM2_LISTADOS.ID_CLASES_LISTADOS, PARAM2_LISTADOS.PLANTILLA, PARAM2_LISTADOS.POR_DEFECTO FROM PARAM2_LISTADOS WHERE PARAM2_LISTADOS.ID_CLASES_LISTADOS=([PARCLASE]) ORDER BY PARAM2_LISTADOS.POR_DEFECTO DESC, PARAM2_LISTADOS.PLANTILLA ASC" );
m_query->Create( "", m_sql );
m_query->SetParamValue( 0, m_idClasesListados );
if( m_set->IsOpen() == TRUE )
m_set->Close(); // ***** POSSIBLE MEMORY LEAK ********
m_set->Open( m_query, dbOpenDynaset );
CargaVariables();
}
Es mejor (para el tema de la memoria) destruir el objeto y volverlo a crear cada vez:void
CParam2ListadosSinSedes::MontarRecordset( BOOL usaDefaultSede /*=TRUE*/ )
{
BorraDaoPuntero( &m_query );
m_query = new CInDaoQueryDef( m_db );
m_sql = _T( "PARAMETERS PARCLASE Long;SELECT PARAM2_LISTADOS.ID_PARAM2_LISTADOS, PARAM2_LISTADOS.ID_CLASES_LISTADOS, PARAM2_LISTADOS.PLANTILLA, PARAM2_LISTADOS.POR_DEFECTO FROM PARAM2_LISTADOS WHERE PARAM2_LISTADOS.ID_CLASES_LISTADOS=([PARCLASE]) ORDER BY PARAM2_LISTADOS.POR_DEFECTO DESC, PARAM2_LISTADOS.PLANTILLA ASC" );
m_query->Create( "", m_sql );
m_query->SetParamValue( 0, m_idClasesListados );
BorraDaoPuntero( &m_set );
m_set = new CInDaoRecordset( m_db );
m_set->Open( m_query, dbOpenDynaset );
CargaVariables();
}
_________________________________________________________________________________________________________
CPlusPlusApuntesC [camelCaseWordsEnabled: false]