Diversas situaciones de fuga de memoria C++/memoria fuera de los límites, así como prevención e investigación

Tabla de contenido

1. Fuga de memoria

1. Introducción

Dos, varios escenarios de pérdida de memoria

3. Prevención e investigación

1, puerta de elección

Dos, memoria fuera de los límites

1. Introducción

Dos, varios casos de memoria fuera de límites

3. Prevención e investigación


1. Fuga de memoria

1. Introducción

  • Una fuga de memoria se refiere a la memoria que se aplica dinámicamente en el código del programa, y ​​la memoria en el montón no se libera después de su uso por alguna razón, lo que resulta en una pérdida de memoria.
  • Una pequeña cantidad de pérdidas de memoria no afectará el funcionamiento normal del programa, pero si se trata de una pérdida de memoria continua, la memoria del sistema se agotará y, finalmente, el programa se congelará o incluso el sistema colapsará. Para evitar un bloqueo del sistema, cuando no se puede aplicar la memoria, se debe llamar con decisión a la función exit() para eliminar activamente el proceso en lugar de intentar guardarlo.

Dos, varios escenarios de pérdida de memoria

1. La memoria solicitada por malloc/new no se libera activamente

void test1()
{
	char* str = new char[100];
	
	/*delete[] str; 这里忘记delete了 */
}

2. Nuevo y gratuito son mixtos, malloc y delete son mixtos

class Base
{
public:
	int* values;
	Base() { values = new int[100]; }
	~Base() { delete[] values; }
};

void test2()
{
	Base* pBase = new Base;

	free(pBase);	
	/* 错误,这样只会释放pBase指向的内存,却不会调用Base的析构函数
	 会导致Base中的values指向的内存无法被释放 */

	delete pBase;	/* 正确 */
}

3. Al usar new para crear una matriz, delete olvida agregar []

void test3()
{
	int* vects = new int[100];

	delete vects;	// 这种写法是错误的
	delete[] vects;	// 这种写法是正确的
}

4. El destructor de la clase base no está definido como una función virtual

class A
{
public:
	A() {}
	~A() {}
};

class B : public A
{
public:
	B() { num = new int[100]; }
	~B() { delete[] num; }
private:
	int* num;
};

void main() {
	A* pa = new B();

	delete pa;
	/* 这样只会调用A类的析构函数,而B类中的num就得不到释放
	正确的是应该把A的析构类声明为虚函数 */
}

3. Prevención e investigación

1, puerta de elección

  • Entorno de aplicación: Linux
  • Lenguaje de programación: C/C++
  • Cómo usarlo: agregue la opción -g al compilar, como gcc -g filename.c -o filename, y use el siguiente comando para verificar el uso de la memoria:
  • Salida de resultado: #valgrind --tool=memcheck --leak-check=yes --show-reachable=yes ./filename, verá el informe de uso de memoria
  • Idea de diseño: mantener una tabla de espacios de direcciones válida y una tabla de espacios de direcciones no válida (el espacio de direcciones del proceso) de acuerdo con la operación de memoria del software
  • Pros y contras: Capacidad para detectar:
    • Uso de memoria no inicializada
    • Usar memoria que ha sido liberada (Memoria de lectura/escritura después de haber sido liberada)
    • Uso de más espacio de memoria asignado que malloc (lectura/escritura del final de los bloques malloc)
    • Acceso ilegal a la pila (lectura/escritura en áreas inapropiadas de la pila)
    • Si se ha liberado el espacio solicitado (fugas de memoria, donde los punteros a los bloques malloc se pierden para siempre)
    • malloc/free/new/delete aplicación y liberación de coincidencia de memoria (uso no coincidente de malloc/new/new [] frente a free/delete/delete [])
    • Superposición de punteros src y dst en memcpy() y funciones relacionadas
    • repetir gratis
  • Cómo conseguirlo: http://valgrind.org/

2. Usa punteros inteligentes

void test4()
{
	// 以下两种写法效果相同
	shared_ptr<int> p1 = shared_ptr<int>(new int(234));
	shared_ptr<int> p2 = make_shared<int>(234);

	// 还有其他指针指针
	weak_ptr<int>   p3 = weak_ptr<int>(p1);
	unique_ptr<int> p4 = unique_ptr<int>(new int(234));
	auto_ptr<int>   p5 = auto_ptr<int>(new int(234));
}

Dos, memoria fuera de los límites

1. Introducción

  • La memoria fuera de los límites es uno de los principales errores en los sistemas de software, y sus consecuencias suelen ser impredecibles y muy graves. Lo que es más problemático es que el momento de su aparición es aleatorio, los síntomas que presenta son aleatorios y las consecuencias también son aleatorias, lo que dificulta que los programadores descubran la conexión entre el fenómeno y la esencia de estos errores, por lo que Trae una gran dificultad para localizar el error. En general, el acceso fuera de los límites de la memoria se puede dividir en los siguientes dos tipos:
  • Leer fuera de los límites significa leer datos que no le pertenecen. Si la dirección de la memoria de lectura no es válida, el programa falla de inmediato; si la dirección de la memoria de lectura es válida, no habrá problemas inmediatos al leer, pero debido a que los datos de lectura son aleatorios, tendrá consecuencias impredecibles.
  • Escribir fuera de los límites, también conocido como desbordamiento de búfer, los datos escritos son aleatorios para otros programas y también causará consecuencias impredecibles.

Dos, varios casos de memoria fuera de límites

  1. Cuando se define el puntero, no se inicializa, por lo que apunta a un valor aleatorio y el usuario no tiene necesariamente derechos de acceso.
  2. La memoria asignada es menor que la memoria utilizada real.
  3. Subíndice incorrecto al usar el subíndice para acceder a la matriz.
  4. Se ha liberado la memoria, pero aún se utilizan punteros para utilizar esta memoria.

3. Prevención e investigación

  1. Al definir una variable de puntero, si no la inicializa temporalmente, puede dejar que apunte a nullptr primero.
  2. Al asignar memoria, el usuario debe comprobar si la memoria se ha asignado correctamente.
  3. Cuando utilice un subíndice para acceder a una matriz, compruebe si está fuera de los límites.
  4. Una vez que se libera la memoria, al puntero que apunta a esta memoria también se le debe asignar un valor de nullptr.

Supongo que te gusta

Origin blog.csdn.net/iuu77/article/details/129843314
Recomendado
Clasificación