[C++] Memory management, new and delete operation types, operator new and operator delete functions, implementation principles of new and delete

1. C/C++ memory management

  In C/C++, memory management is the process by which the programmer is responsible for managing the computer's memory. Memory management involves allocating and freeing computer memory to store information such as variables, objects, data structures, and segments of program code.

  In C/C++, programmers need to manually allocate and free memory to avoid problems such as memory leaks, memory errors, and fragmentation. The malloc and free functions are used in C language to allocate and release memory, and the new and delete operators are used in C++ to achieve the same purpose.

insert image description here

  In a C++ program, memory can be divided into the following parts:

(1) Stack : Non-static local variables/function parameters/return values, etc., the stack grows downward.

(2) Memory mapping segment : It is an efficient I/O mapping method for loading a shared dynamic memory bank. Users can use the system interface to create shared shared memory for inter-process communication.

(3) Heap : It is used for dynamic memory allocation when the program is running, and the heap can grow upwards.

(4) Data segment : store global data and static data.

(5) Code segment : executable code/read-only constant
insert image description here

2. The memory management method of C language

(1) Stack memory allocation : Stack memory allocation is automatically allocated and released by the system. When a function is called, the parameters and local variables of the function are allocated on the stack. When the function call ends, the data in the stack will be automatically released. Stack memory is a limited resource, and if there is not enough stack space, the program may fail.

void bar()
{
    
    
    int x = 42; // 分配到栈上
}

int main() {
    
    
    bar();
    return 0;
}


(2) Heap memory allocation : Heap memory allocation is dynamic memory that is manually allocated and released by the programmer during program execution. The size of the heap memory depends on the size of the memory block requested by the programmer, and its lifetime is not fixed. In the C language, dynamic allocation of memory is usually performed using the malloc(), calloc(), realloc(), and free() functions.

  Introduction to Dynamic Memory Allocation in C Language

int main() 
{
    
    
	int* p1 = (int*) malloc(sizeof(int));
	free(p1);
	int* p2 = (int*)calloc(4, sizeof (int));
	int* p3 = (int*)realloc(p2, sizeof(int)*10);
	free(p3 );
}

(3) Static memory allocation : Static memory allocation is memory automatically allocated by the compiler during program compilation. Global variables, static variables, constants, and strings are usually stored in static memory, and will not be released during program execution, such as variables declared by keywords such as static and const.

#include <stdio.h>

int g_global_var; //全局变量

int main()
{
    
    
    static int s_static_var; //静态局部变量
    return 0;
}


(4) Memory pool : Memory pool is a technology that pre-allocates a large block of memory at startup. This memory can be used to store variables and data structures of the program to reduce frequent memory allocation and release operations when the remaining memory is insufficient. Memory pools can be used to improve program performance and reduce memory fragmentation that occurs during memory allocation.

3. C++ memory management method

  In C language, the commonly used memory management methods such as malloc and free can continue to be used in C++, but there are some places where there is nothing they can do, and it is more troublesome to use, so C++ has proposed its own memory management method: through the new and delete operators Perform dynamic memory management.

3.1 new and delete operation built-in types

   new: Used to dynamically allocate memory and return a pointer to the allocated object or object array.

  delete: Used to release dynamically allocated memory, it needs to match new, otherwise it may cause memory leaks or invalid operations.

  When using new and delete, you need to pay attention to the following points:

(1) For the allocation and release of a single object, the new and delete operators can be used:

int* ptr = new int; // 分配一个整型变量的大小

delete ptr; // 释放内存,避免内存泄漏


(2) It can be initialized when assigning a single object:

int* ptr = new int(40); // 分配一个整型变量的大小

delete ptr; // 释放内存,避免内存泄漏


(3) For the allocation and release of arrays, you can use the new[] and delete[] operators:

int* arr = new int[4]; // 分配一个int类型的数组,大小为4
for (int i = 0; i < 4; ++i) {
    
    
    arr[i] = i;
}

delete[] arr; // 释放内存


(4) When using new, if the required memory cannot be allocated, a std::bad_alloc exception will be thrown, and try-catch needs to be used to catch the exception:

try {
    
    
    int *p = new int[1024*1024*1024];
} catch (const std::bad_alloc& e) {
    
    
    std::cout << "Allocation failed: " << e.what() << std::endl;
}


  Note: To apply for and release the space of a single element, use the new and delete operators, to apply for and release continuous space, use new[] and delete[], note: use them together.

insert image description here

3.2 new and delete operation custom type

  Note: When applying for a custom type of space, new will call the constructor, delete will call the destructor, but malloc and free will not.

class A
{
    
    
public:
	A(int a = 0)
		: _a(a)
	{
    
    
		cout << "A():" << this << endl;
	}

	~A()
	{
    
    
		cout << "~A():" << this << endl;
	}
private:
	int _a;
};

int main()
{
    
    
	// new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】除了开空间
	还会调用构造函数和析构函数
	A* p1 = (A*)malloc(sizeof(A));
	A* p2 = new A(1);
	free(p1);
	delete p2;
	
	// 内置类型是几乎是一样的
	int* p3 = (int*)malloc(sizeof(int)); // C
	int* p4 = new int;
	free(p3);
	delete p4;
	
	A* p5 = (A*)malloc(sizeof(A)*10);
	A* p6 = new A[10];
	free(p5);
	delete[] p6;
	return 0;
}

  The memory management method in C++ is based on the management method of C language. Not only has new and delete types, C++ also introduces some other memory management methods, such as: RAII (Resource Acquisition Is Initialization), smart pointers, STL containers, etc. .

4. operator new and operator delete functions

  The operator new and operator delete functions are functions in the C++ standard library for dynamic memory allocation and release. They are basic tools for C++ memory management, can be used for dynamic memory management of custom types, and can also be used to overload the default new and delete operators.

  The operator new function is used to allocate an uninitialized memory block of a specified size from the heap. Its basic syntax is as follows:

void* operator new (size_t size);
void* operator new[] (size_t size);

  In short: new and delete are operators for users to apply and release dynamic memory. operator new and operator delete are global functions provided by the system. free up space.

/*
operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;
申请空间失败,尝试执行空间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。
*/

void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{
    
    
// try to allocate size bytes
void *p;
while ((p = malloc(size)) == 0)
	if (_callnewh(size) == 0)
	{
    
    
		// report no memory
		// 如果申请内存失败了,这里会抛出bad_alloc 类型异常
		static const std::bad_alloc nomem;
		_RAISE(nomem);
	}
return (p);
}

/*
operator delete: 该函数最终是通过free来释放空间的
*/

void operator delete(void *pUserData)
{
    
    
     _CrtMemBlockHeader * pHead;
     RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));
     if (pUserData == NULL)
         return;
     _mlock(_HEAP_LOCK);  /* block other threads */
     __TRY
         /* get a pointer to memory block header */
         pHead = pHdr(pUserData);
          /* verify block type */
         _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
         _free_dbg( pUserData, pHead->nBlockUse );
     __FINALLY
         _munlock(_HEAP_LOCK);  /* release other threads */
     __END_TRY_FINALLY
     return;
}

/*
free的实现
*/

#define   free(p)               _free_dbg(p, _NORMAL_BLOCK)

  Through the implementation of the above two global functions, we know that operator new actually applies for space through malloc . If the malloc application space is successful, it returns directly. Otherwise, it executes the solution to the lack of space provided by the user. If the user provides this measure, it continues to apply. Otherwise, it returns Throw an exception. operator delete finally releases space through free.

5. Implementation principle of new and delete

5.1 Built-in types

  If you apply for a built-in type of space, new and malloc, delete and free are basically similar, the difference is:
  new/delete applies for and releases the space of a single element, new[] and delete[] apply for continuous space, Moreover, new will throw an exception when it fails to apply for space, and malloc will return NULL.

5.2 Custom types

The principle of new:
(1) Call the operator new function to apply for space
(2) Execute the constructor on the applied space to complete the construction of the object

The principle of delete:
(1) Execute the destructor on the space to complete the cleanup of resources in the object
(2) Call the operator delete function to release the space of the object

The principle of new T[N]
(1) Call the operator new[] function, and actually call the operator new function in operator new[] to complete the application of N object
spaces
(2) Execute the constructor N times on the applied space

The principle of delete[]:
(1) Execute N times of destructors on the released object space to complete the cleanup of resources in N objects
(2) Call operator delete[] to release space, and actually call operator in operator delete[] delete to free
up space

Guess you like

Origin blog.csdn.net/Crocodile1006/article/details/131341747