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 _DEBUG #endif
#ifdef _DEBUG #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: Y al acabar el código a examinar: 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]