Red de conocimiento informático - Conocimiento del nombre de dominio - ¿Cómo comprobar usted mismo el código NodeJS en busca de pérdidas de memoria?

¿Cómo comprobar usted mismo el código NodeJS en busca de pérdidas de memoria?

Primero, verificamos el código y descubrimos que todos los códigos usan nuevo para asignar memoria y eliminar para liberar memoria. Entonces, ¿podemos reemplazar todos los operadores nuevos y eliminados con un reemplazo completo? No puedo. Debido a que el tamaño del código es demasiado grande, no hay ningún beneficio excepto una pérdida de tiempo. Afortunadamente, nuestro código fuente está escrito en C++, por lo que esto significa que no es necesario reemplazar todos los operadores nuevos y de eliminación, solo es necesario sobrecargar estos dos operadores. Por cierto, al sobrecargar estos dos operadores con valores, podemos hacer algo antes de asignar y liberar memoria. Esta es definitivamente una buena noticia. También sabemos cómo hacerlo. Porque MFC hace lo mismo. Lo que debemos hacer es: realizar un seguimiento de todas las asignaciones de memoria, referencias cruzadas y liberaciones de memoria. Nuestro código fuente está escrito en Visual C++, pero, por supuesto, esta solución también se puede utilizar fácilmente en otro código C++. Lo primero que debe hacer es sobrecargar los operadores nuevo y eliminar, que se utilizarán en todo el código. En stdafx.h, agregamos:

#ifdef _DEBUG

Inline void * __cdecl operator new (unsigned int size,

const char *file, int line )

{

};

Eliminación del operador __cdecl en línea (void *p)

{

};

#endif

De esta forma sobrecargamos los operadores new y delete. Envolvemos estos dos operadores sobrecargados con $ifdef y #endif para que estos dos operadores no aparezcan en la versión de lanzamiento. Si observa este código, verá que el nuevo operador toma tres argumentos, que son el tamaño de la memoria asignada, el nombre del archivo en el que aparece y el número de línea. Esto es necesario e importante para encontrar pérdidas de memoria. De lo contrario, llevará mucho tiempo saber dónde aparecen exactamente. Con este código, nuestro código que llama a new() todavía apunta a un nuevo operador que toma solo un argumento, en lugar de un operador que toma tres argumentos. Además, no queremos registrar que todas las declaraciones del nuevo operador contengan los parámetros __FILE__ y __LINE__. Lo que debemos hacer es hacer que todos los operadores nuevos que toman un argumento llamen automáticamente a operadores nuevos que toman tres argumentos. Esto requiere un poco de habilidad, como la siguiente definición de macro,

#ifdef _DEBUG

#define DEBUG_NEW new(__FILE__, __LINE__)

#Otherwise

#define DEBUG_NEW new

#endif

#Define new DEBUG_NEW

Ahora todos nuestros nuevos operadores que aceptan un parámetro se convierten en nuevos operador que acepta tres parámetros, y el precompilador inserta automáticamente __FILE__ y __LINE__. Luego, está el seguimiento real. Necesitamos agregar algunas rutinas a nuestras funciones sobrecargadas para que puedan asignar y liberar memoria. Para hacer esto, #ifdef _DEBUG

inline void * __cdecl operador nuevo (unsigned int size,

const char *file, int line)

{

void * ptr = (void *)malloc(tamaño);

AddTrack((DWORD)ptr, tamaño, archivo, línea);

Return (ptr) ;

};

El operador __cdecl anulado en línea elimina (void *p)

{

eliminar pista( (DWORD)p) ;

Gratis(p);

};

#endif

Además, necesita una forma de sobrecargar el nuevo[ ] y eliminar [] operadores. Omitido aquí.

Finalmente, necesitamos proporcionar un conjunto de funciones AddTrack() y RemoveTrack(). Utilizo STL para mantener una tabla de unión que almacena registros de asignación de memoria.

Las dos funciones son las siguientes:

estructura typedef {

Dirección de palabra doble

Tamaño de palabra doble

;

archivo char[64];

línea DWORD;

} ALLOC _ INFO

lista typedef & ltALLOC _ INFO * & gtAllocList

AllocList * allocList

void AddTrack(DWORD addr, DWORD asize, const char *fname, DWORD lnum)

{

ALLOC _ INFO * info

If (!allocList) {

allocList = nuevo(allocList);

}

INFO = nuevo(ALLOC _ INFO)

info->address=addr

strncpy(info->file,fname,63);

info->line= lnum<; /p>

Información->tamaño = asize

allocList->insert(allocList->begin(), info);

} ;

void RemoveTrack(doble dirección)

{

AllocList::Iterator I;

If (!allocList)

Regresar ;

for(I = allocList-& gt; comenzar(); I! = allocList-& gt; end(); i++)

{

if((* I)-& gt; dirección == dirección)

{

allocList-& gt; eliminar ((* I)); Break;

}

}

};

Ahora, antes de que nuestro programa salga, allocList almacena asignaciones de memoria que aún no han sido liberado. Para ver qué son y dónde están asignados, necesitamos imprimir los datos en allocList. Utilizo la ventana de salida en Visual C++ para lograr esto.

void DumpUnfreed()

{

AllocList::Iterator I;

Tamaño total de DWORD = 0;

char buf[1024];

if(!allocList)

return;

for(I = allocList->begin(); i! = allocList-> end(); i++) {

sprintf(buf, "%-50s: Línea %d, dirección %d %d no publicada",

(* I)->Archivo, (*I)->Línea, (*I)->Dirección, (*I)->Tamaño);

OutputDebugString (buf);

tamaño total+=(* I)-& gt; tamaño;

}

sprintf(buf, "-");

p>

OutputDebugString(buf);

sprintf(buf, "Cantidad total no publicada: %d bytes", Tamaño total);

OutputDebugString(buf);

};

Ahora tenemos un código reutilizable para monitorear y rastrear todas las pérdidas de memoria. Este código se puede agregar a todos los proyectos. Aunque no hará que su programa se vea mejor, al menos puede ayudarlo a verificar si hay errores y hacer que el programa sea más estable.