Solución:
Instrucciones
Cosas que necesitará
- Competencia en C ++
- Compilador de C ++
- Depurador y otras herramientas de software de investigación
1
Comprender los conceptos básicos del operador. El operador C ++ new
asigna memoria de pila. los delete
El operador libera la memoria del montón. Para cada new
, deberías usar un delete
para que libere la misma memoria que asignó:
char* str = new char [30]; // Allocate 30 bytes to house a string.
delete [] str; // Clear those 30 bytes and make str point nowhere.
2
Reasigne la memoria solo si la ha eliminado. En el siguiente código, str
adquiere una nueva dirección con la segunda asignación. La primera dirección se pierde irremediablemente, al igual que los 30 bytes a los que apuntaba. Ahora es imposible liberarlos y tiene una pérdida de memoria:
char* str = new char [30]; // Give str a memory address.
// delete [] str; // Remove the first comment marking in this line to correct.
str = new char [60]; /* Give str another memory address with
the first one gone forever.*/
delete [] str; // This deletes the 60 bytes, not just the first 30.
3
Mire esas asignaciones de punteros. Cada variable dinámica (memoria asignada en el montón) debe estar asociada con un puntero. Cuando una variable dinámica se disocia de su (s) puntero (s), resulta imposible borrarla. Nuevamente, esto da como resultado una pérdida de memoria:
char* str1 = new char [30];
char* str2 = new char [40];
strcpy(str1, "Memory leak");
str2 = str1; // Bad! Now the 40 bytes are impossible to free.
delete [] str2; // This deletes the 30 bytes.
delete [] str1; // Possible access violation. What a disaster!
4
Tenga cuidado con los indicadores locales. Un puntero que declara en una función se asigna en la pila, pero la variable dinámica a la que apunta se asigna en el montón. Si no lo elimina, persistirá después de que el programa salga de la función:
void Leak(int x){
char* p = new char [x];
// delete [] p; // Remove the first comment marking to correct.
}
5
Preste atención a las llaves después de “eliminar”. Usar delete
por sí mismo para liberar un solo objeto. Usar delete []
con corchetes para liberar una matriz de montón. No hagas algo como esto:
char* one = new char;
delete [] one; // Wrong
char* many = new char [30];
delete many; // Wrong!
6
Si la fuga ya se ha permitido, normalmente la busco con deleaker (compruébalo aquí: http://deleaker.com).
Puede utilizar algunas técnicas en su código para detectar pérdidas de memoria. La forma más común y fácil de detectar es definir una macro, por ejemplo, DEBUG_NEW y usarla, junto con macros predefinidas como __FILE__
y __LINE__
para localizar la pérdida de memoria en su código. Estas macros predefinidas le indican el archivo y el número de línea de las pérdidas de memoria.
DEBUG_NEW es solo una MACRO que generalmente se define como:
#define DEBUG_NEW new(__FILE__, __LINE__)
#define new DEBUG_NEW
Para que donde sea que uses new
, también puede realizar un seguimiento del archivo y el número de línea que podría utilizarse para localizar la pérdida de memoria en su programa.
Y __FILE__
, __LINE__
son macros predefinidas que evalúan el nombre de archivo y el número de línea, respectivamente, donde los usa.
Lea el siguiente artículo que explica muy bien la técnica de usar DEBUG_NEW con otras macros interesantes:
Un detector de fugas de memoria multiplataforma
De Wikpedia,
Debug_new se refiere a una técnica en C ++ para sobrecargar y / o redefinir operador nuevo y operador eliminar para interceptar la asignación de memoria y las llamadas de desasignación, y así depurar un programa para el uso de memoria. A menudo implica definir una macro llamada DEBUG_NEW y hace que lo nuevo se convierta en algo como nuevo (_EXPEDIENTE_, _LÍNEA_) para registrar la información de archivo / línea sobre la asignación. Microsoft Visual C ++ utiliza esta técnica en sus Microsoft Foundation Classes. Hay algunas formas de ampliar este método para evitar el uso de la redefinición de macros y, al mismo tiempo, poder mostrar la información de archivo / línea en algunas plataformas. Hay muchas limitaciones inherentes a este método. Se aplica solo a C ++ y no puede detectar pérdidas de memoria por funciones de C como malloc. Sin embargo, puede ser muy simple de usar y también muy rápido, en comparación con algunas soluciones de depuración de memoria más completas.
Existen algunas técnicas de programación bien conocidas que le ayudarán a minimizar el riesgo de sufrir pérdidas de memoria de primera mano:
- si tiene que hacer su propia asignación de memoria dinámica, escriba
new
ydelete
siempre por pares, y asegúrese de que el código de asignación / desasignación se llame por pares - evite la asignación de memoria dinámica si puede. Por ejemplo, use
vector<T> t
siempre que sea posible en lugar deT* t = new T[size]
- use “punteros inteligentes” como los punteros inteligentes boost (http://www.boost.org/doc/libs/1_46_1/libs/smart_ptr/smart_ptr.htm)
- mi favorito personal: asegúrese de haber entendido el concepto de propiedad de un puntero, y asegúrese de que en todos los lugares donde use punteros, sepa qué entidad de código es el propietario
- aprenda qué constructores / operadores de asignación son creados automáticamente por el compilador de C ++, y qué significa eso si tiene una clase que posee un puntero (o qué significa eso si tiene una clase que contiene un puntero a un objeto, sí no propio).