[C / C ++] ¡No te puedes perder la gestión de memoria C / C ++!

1. Distribución de memoria C / C ++

  • Primero mira un fragmento de código:
int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{
    
    
 static int staticVar = 1;
 int localVar = 1;
 
 int num1[10] = {
    
    1, 2, 3, 4};
 char char2[] = "abcd";
 char* pChar3 = "abcd";
 int* ptr1 = (int*)malloc(sizeof (int)*4);
 int* ptr2 = (int*)calloc(4, sizeof(int));
 int* ptr3 = (int*)realloc(ptr2, sizeof(int)*4);
 free (ptr1);
 free (ptr3);
}

Ubicación correspondiente en la memoria:
Inserte la descripción de la imagen aquí

  • Pila: almacena parámetros de función, variables locales e información de registro (la función finaliza, se libera el marco de pila) y la pila crece hacia abajo
    • El tamaño de espacio de pila predeterminado en Linux: 8192kb = 8M
    • Espacio de pila de Windows: 1024kb = 1M
  • Montón: aplicación de memoria dinámica, malloc, calloc, realloc, debe liberarse con free, el montón crece hacia arriba
  • Segmento de datos: variables globales, datos modificados por estática (el ciclo de vida es consistente con el programa, el programa sale, los datos se borran)
  • Fragmento de código: código y constantes de solo lectura

¿Por qué dividir la memoria en diferentes áreas?
El tipo de datos es diferente, el método de gestión de datos también es diferente, con el fin de facilitar la búsqueda para dividir diferentes áreas.

Dos, gestión de la memoria

2.1 Gestión de la memoria en lenguaje C:

malloc 、 calloc 、 realloc

int* p1 = (int*)malloc(sizeof(int));		// 动态申请int空间大小,随机值
int* p2 = (int*)calloc(4, sizeof(int));		// 动态申请int空间大小,并赋值4
int* p3 = (int*)realloc(p2, sizeof(int) * 10);	//调整p2的空间大小为10个int大小

Mismo punto:

  1. El valor devuelto es nulo *, debe ser obligado a transferir al recibir
  2. La aplicación no devuelve NULL, por lo que debe estar vacía antes de su uso.

diferencia:

  1. malloc (tamaño): solo solicite la memoria del tamaño del tamaño
  2. calloc (num, size): el tamaño del espacio de la aplicación es size y el valor se asigna a los datos
  3. realloc (void * p, size): Ajusta el tamaño del espacio apuntado por p al tamaño (agrandar o encoger) Si p es NULL, la función es similar a malloc. Si el tamaño del espacio detrás de p es menor que el tamaño, busque un nuevo espacio que tenga el tamaño suficiente, copie el contenido del espacio anterior y finalmente libere el tamaño del espacio anterior.

Nota: El espacio de memoria solicitado por malloc será un poco más grande de lo esperado. En el modelo de objetos, hay 32 bytes de información de atributos (incluido el tamaño de la memoria solicitada, etc.) y hay una posición final de 4 bytes en la espalda para evitar fuera de límites.

2.2 Gestión de memoria C ++:

¿Por qué C ++ crea un nuevo método de administración de memoria?
C ++ es una programación orientada a objetos. Utiliza malloc, calloc y realloc para abrir dinámicamente el tamaño del espacio de clases. No llama al constructor, por lo que no se puede llamar un objeto. Cuando se llama a free, el destructor no se puede llamar para limpiar los recursos internos del objeto. Puede causar pérdidas de memoria

  1. Solicitar / liberar un solo tipo de espacio: nuevo / eliminar
  2. Aplicar / liberar espacio de texto continuo: nuevo [] / eliminar []

Aplicación dinámica para tipos integrados:

int* p1=new int(10);10初始化
int* p2=new int[10]{
    
    1,2,3,4,5,6,7,8,9,0}; 申请连续空间并初始化
delete p1;
delete[] p2;

Aplicación dinámica para tipos personalizados:

class Test
{
    
    
public:
    Test(int p = 0)
        :p_(p)
    {
    
    
        cout << "构造:" << this << endl;
    }
    ~Test()
    {
    
    
        cout << "析构:" << this << endl;
    }
private:
    int p_;
};

int main()
{
    
    
    Test* p1 = new Test(100);				//会调用构造函数(类内成员t被初始化成1),因此生成的为对象
    Test* p2 = (Test*)malloc(sizeof(Test));	//不会调用(类内成员t没有初始化),因此只能称为和类类型大小相同的堆空间
    delete p1;								//会调用析构函数,清理
    free(p2);								//只会释放开辟的空间
    return 0;
}

La diferencia entre malloc y new:

  1. new es una palabra clave en C ++, malloc es una función de biblioteca, por lo que el archivo de encabezado debe introducirse antes de su uso
  2. la aplicación malloc / liberación de espacio no llamará al constructor / destructor, new llamará al constructor / destructor
  3. La aplicación malloc falla y devuelve NULL. Debido a la implementación interna de new, no hay devolución de un puntero nulo.
  4. El valor de retorno de malloc es nulo * y new devuelve un puntero del tipo correspondiente, por lo que no es necesario forzar la transferencia para recibir

Nota:
nuevo / eliminar, nuevo [] / eliminar [], malloc \ free deben coincidir; de lo contrario, el programa se bloqueará o se perderá la memoria.

class Test
{
    
    
public:
    Test(int val = 0)
        :p_(new int(val))
    {
    
    
        cout << "构造:" << this << endl;
    }
    ~Test()
    {
    
    
        delete p_;
        cout << "析构:" << this << endl;
    }
private:
    int* p_;
};

int main()
{
    
    
    Test* p1 = (Test*)malloc(sizeof(Test));
    Test* p2 = new Test;
    Test* p3 = new Test[2];
    
    delete p1;      // 程序崩溃,malloc没有调用构造函数
    delete[] p1;    // 程序崩溃,malloc没有调用构造函数

    free(p2);       // 内存泄漏,free没有调用析构函数

    free(p3);       // 程序崩溃,连续空间只释放了一部分
    delete p3;      // 程序崩溃,连续空间只释放了一部分
    return 0;
}

Tres, nuevo / eliminar flujo de trabajo

3,1 nuevo

  • 1. Solicita espacio en la pila
    • Llame a la función void * operator new (size) para solicitar espacio, el tamaño es el tamaño del espacio de la clase y llame a malloc internamente para solicitar espacio
      • Éxito: volver a la primera dirección del espacio
      • Fallo: llamar a la función _callnewh (tamaño), llamar a la solución proporcionada por el usuario, si falla, lanzar una excepción de tipo bad_alloc, continuar solicitando espacio
  • 2. Llame al constructor para inicializar el espacio solicitado

Resumen: debido a la forma en que se ejecuta la función del operador new (), new no devolverá nulo

3.2 eliminar

  • 1. Llame al destructor para limpiar los recursos del objeto.
  • 2. Llame a la función delete () del operador, llame internamente gratis para liberar espacio

3,3 nuevo []

  • 1. Para solicitar espacio, llame al operador void * new [] (tamaño) y llame internamente a la función del operador new () para solicitar N espacios de clase
  • 2. Llame al constructor N veces para inicializar N objetos

3.4 eliminar []

  • 1. Llame al destructor N veces para limpiar los recursos espaciales señalados por p
  • 2. Llame a anular la eliminación del operador [] (anular * p) para liberar el espacio señalado por p—> la función de eliminación del operador se llama internamente

Cuarto, convierta el espacio de clase abierto por malloc en objetos.

  • El espacio solicitado por malloc no se puede llamar objeto, porque el constructor no se llama
  • Coloque la nueva expresión: llame al constructor en el espacio de pila abierto, inicialice el espacio de clases y conviértalo en un objeto
#include<iostream>
using namespace std;
class Test
{
    
    
public:
	Test(int t = 0)
		:_t(t), _p(new int)
	{
    
    
		cout << "Test(int):" << endl;
	}
	~Test()
	{
    
    
		delete _p;
		cout << "~Test():" << this << endl;
	}
private:
	int _t;
	int* _p;
};
int main()
{
    
    
	Test* pt = (Test*)malloc(sizeof(Test));
	new(pt) Test(100);		// 定位new表达式
	pt->~Test();			// 调用析构函数清理资源
	free(pt);				// 调用free释放空间
	return 0;
}

Supongo que te gusta

Origin blog.csdn.net/qq_45691748/article/details/110225950
Recomendado
Clasificación