Red de conocimiento informático - Computadora portátil - ¿En qué circunstancias se producirá una pérdida de memoria en el contenedor de la biblioteca estándar de C++?

¿En qué circunstancias se producirá una pérdida de memoria en el contenedor de la biblioteca estándar de C++?

¿Cómo lidiar con las pérdidas de memoria?

Escribir código que no provoque pérdidas de memoria. Obviamente, cuando su código está lleno de operaciones nuevas, operaciones de eliminación y aritmética de punteros, se confundirá en alguna parte, lo que provocará pérdidas de memoria, referencias erróneas de punteros, etc. No importa qué tan cuidadoso seas con la asignación de memoria, la complejidad de tu código siempre excederá el tiempo y esfuerzo que puedas invertir. Han surgido técnicas exitosas que se basan en ocultar la asignación y desasignación detrás de tipos manejables. Los contenedores estándar son un buen ejemplo. En lugar de que usted administre la memoria del elemento, ellos mismos administran la memoria, evitando así malos resultados. Imagínese, ¿podría escribir ese código sin la ayuda de cadenas y vectores?

#include

#include

#include

#include

#include

# include

usando el espacio de nombres std;

int main() // Procesando cadenas Mini programa

{

cout <<."ingrese algunas palabras separadas por espacios en blanco:\n";

vector v;

cadena s;

mientras (cin>>s) v.push_back(s);

sort(v.begin(),v.end());

sort( v. comenzar(),v.end());

string cat;

typedef vector::const_iterator Iter;

for (Iter p = v.begin(); p!=v.end(); ++p) gato += *p+"+";

cout << gato << '\n';

}

¿Cuáles son tus posibilidades de hacerlo bien la primera vez? ¿Cómo sabes que no estás provocando una pérdida de memoria?

Tenga en cuenta que no utilizamos administración de memoria explícita, macros, modelado, verificación de desbordamiento, límites de longitud explícitos ni punteros. Podría evitar el uso de punteros usando objetos de función y algoritmos estándar, por ejemplo usando iteradores, pero esto es un poco trivial para un programa tan pequeño.

Estas técnicas no son perfectas y utilizarlas sistemáticamente no es fácil. Sin embargo, aplicar estas técnicas puede marcar una diferencia sorprendente e incluso puede hacer que los ejemplos restantes sean más fáciles de entender al reducir la cantidad de asignaciones y reasignaciones de memoria explícitas. En 1981, señalé que al reducir la cantidad de objetos que tenía que rastrear explícitamente de decenas de miles a docenas, el esfuerzo requerido para lograr que un programa se ejecutara correctamente pasó de ser un trabajo terrible a tratar con unos pocos objetos manejables. más simple.

Si su programa aún no incluye una biblioteca que reduzca la administración de memoria explícita al mínimo, entonces quizás la forma más rápida de hacer que su programa funcione correctamente sea crear dicha biblioteca primero.

La biblioteca de plantillas y la biblioteca estándar implementan contenedores, identificadores de recursos y similares que se han utilizado durante muchos años. El uso de excepciones lo hace aún mejor.

Si realmente no puede ocultar las operaciones de asignación/reasignación de memoria del objeto que necesita, puede utilizar identificadores de recursos para minimizar la posibilidad de pérdidas de memoria. Aquí hay un ejemplo: necesito crear un objeto en la memoria libre y devolverlo a través de una función. En este punto, es posible que me olvide de soltar el objeto. Después de todo, no podemos decir que solo nos importa quién es responsable de hacer esto cuando se publica este puntero.

El uso de un identificador de recursos (aquí aut_ptr de la biblioteca estándar) deja claro quién es el responsable.

#include

#include

usando el espacio de nombres std;

struct S {

S() { cout << "hacer un S\n" }

~S() { cout << "destruir un S\n"; (const S&) { cout << "copiar inicializar un S\n" }

S& operator=( const S&) { cout << "copiar asignar un S\n"; >

};

S* f()

{

return new S; // ¿Quién debería ser responsable de publicar esta S?

};

auto_ptr< ;S> g()

{

return auto_ptr(nueva S); Pase explícitamente a la persona responsable de liberar este S

}

int main()

{

cout << "start main \ n ";

S* p = f();

cout << "después de f() antes de g()/n";

/ / S* q = g(); // Será capturado por el compilador

auto_ptr q = g()

cout << "exit main\n"; ;

cout < < lt; "exit main\n";

// *p Creó una pérdida de memoria

// *q fue liberado por auto_ptr

}

Piense en los recursos en un sentido más amplio, no solo en la memoria.

Si no puedes aplicar estas técnicas sistemáticamente en tu entorno (por ejemplo, debes usar código de otro lugar, o otra parte de tu programa fue creada por un homínido Homo sapiens, neandertales, simios paleolíticos ampliamente distribuido en Europa), etc.), tenga cuidado de utilizar un detector de pérdida de memoria durante el desarrollo o inserte un recolector de basura.