C++ Talking about new/delete, operator new/operator delete, the difference between malloc/free and new/delete, memory leak


1. C/C++ memory distribution

在这里插入图片描述

  • (1) The stack is also called the stack. Non-static local variables/function parameters/return values, etc. are all on the stack, and the stack grows downward.
  • (2) The memory mapped segment is an efficient I/O mapping method for loading a shared dynamic memory library. Users can use the system interface to create shared memory for inter-process communication
  • (3) The heap is used for dynamic memory allocation when the program is running, and the heap grows upwards
  • (4) Data segment – ​​stores global data and static data (variables)
  • (5) Code segment – ​​executable code/read-only constant (constant)

2. Dynamic memory management in C language

malloc/calloc/realloc/free is not detailed here, you can refer to the previous C language column C language dynamic memory management

3. C++ memory management method

The C language memory management method can continue to be used in C++, but in some places it is powerless and cumbersome to use, so C++ has proposed its own memory management method: through the new (new operatornew operator)anddelete operatorDo dynamic memory management

3.1 new/delete operation built-in type

void Test()
{
    
    
	//动态申请一个int类型的空间
	int* ptr = new int;
	//动态申请一个int类型的空间并初始化为20
	//只能初始化单个元素,不能初始化数组
	int* ptr1 = new int(20);
	//动态申请10个int类型的空间
	int* ptr2 = new int[10];

	delete ptr;
	delete ptr1;
	delete[] ptr2;
}

在这里插入图片描述

Note: To allocate space for a single element, use the new and delete operators, to allocate and release contiguous space, use new[] and delete[]

3.2 new (new operator) and delete operate custom types

Running the following code, we will find that: when applying for space of a custom type, new will call the constructor, delete will call the destructor, and malloc and free will not

#include<iostream>
using namespace std;

class Test
{
    
    
public:
	Test() :_data(10)
	{
    
    
		cout << "Test():" << this << endl;
	}
	~Test()
	{
    
    
		cout << "~Test():" << this << endl;
	}
private:
	int _data;
};

void my_malloc_free()
{
    
    
	Test* p = (Test*)malloc(sizeof(Test));
	free(p);
}
void my_new_delete()
{
    
    
	Test* p = new Test;
	delete p;
}
void main()
{
    
    
	Test t;
	my_malloc_free();
	my_new_delete();
}

在这里插入图片描述

So what are the specific steps for new and delete to call the constructor and destructor?

new: apply for space first, then initialize the object
delete: call the destructor first, and then release the space

Verify as follows:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

class String
{
    
    
public:
	String(const char* str)
	{
    
    
		m_date = new char[strlen(str)+1];
		strcpy(m_date, str);
	}
	~String()
	{
    
    
		delete[] m_date;
		m_date = nullptr;
	}
private:
	char* m_date;
};

void main()
{
    
    
	String* p = new String("abc");
	delete p;
}

The diagram is as follows:
在这里插入图片描述

3.3 operator new (operator new) and operator delete functions

new and delete are the operators for users to apply and release dynamic memory , opertor new and operator delete are global functions provided by the system , new calls the operator new global function at the bottom layer to apply for space, and delete uses operator delete (also known as the operator at the bottom layer) new) global function to free space

  • operator new actually applies for space through malloc, the application will be returned directly if the application is successful, and an exception will be thrown if the application fails.
  • operator delete actually releases space through free

Verify as follows:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

void* operator new(size_t sz)
{
    
    
	void* ptr = malloc(sz);
	return ptr;
}
void operator delete(void* ptr)
{
    
    
	free(ptr);
}
void* operator new[](size_t sz)
{
    
    
	void* ptr = malloc(sz);
	return ptr;
}
void operator delete[](void* ptr)
{
    
    
	free(ptr);
}
class String
{
    
    
public:
	String(const char* str)
	{
    
    
		m_date = new char[strlen(str)+1];
		strcpy(m_date, str);
	}
	~String()
	{
    
    
		delete[] m_date;
		m_date = nullptr;
	}
private:
	char* m_date;
};

void main()
{
    
    
	String* p = new String("abc");
	delete p;
}

在这里插入图片描述

3.4 Implementation principle of new and delete

3.4.1 Built-in types

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

3.4.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 [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 delele[]
    (1) Execute N 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 op in operator delete[]

3.5 Positioning new expressions (placement-new)

Positioning the new expression is to call the constructor to initialize an object in the allocated original memory space


Use the format:

new(place_address) type 或者 new (place_address) type(initializer-list)
place_address must be a pointer, initializer-list is an initialization list of the type


scenes to be used:

The positioning new expression is generally used in conjunction with the memory pool in practice. Because the memory allocated by the memory pool is not initialized, if it is an object of a custom type, you need to use the definition expression of new to explicitly call the constructor for initialization.

As shown in the following code:

void main()
{
    
    
	int arr[10] = {
    
    0};

	new(arr) int(10);
}

在这里插入图片描述

Overload positioning new

//重载定位new
void* operator new(size_t sz, int* ar, int pos)
{
    
    
	return &(ar[pos]);
}
void main()
{
    
    
	int arr[10] = {
    
    0};

	new(arr,3) int(22);
}

在这里插入图片描述

3.6 [Interview Questions] The difference between malloc/free and new/delete

What malloc/free and new/delete have in common is that they both apply for space from the heap and need to be released manually by the user. The difference is:

  1. malloc and free are functions, new and delete are operators
  2. The space applied by malloc will not be initialized, new can be initialized
  3. When malloc applies for space, you need to manually calculate the size of the space and pass it, and new only needs to follow the type of space.
  4. The return value of malloc is void*, which must be cast when used, and new is not needed, because new is followed by the type of space
  5. When malloc fails to apply for space, it returns NULL, so it must be empty when using it, new does not need it, but new needs to catch exceptions
  6. When applying for a custom type object, malloc/free will only open up space, and will not call the constructor and destructor, while new will call the constructor to complete the initialization of the object after applying for the space, and delete will call the destructor before releasing the space. Complete the cleanup of resources in the space

4. Memory leak

A memory leak is a situation in which a program fails to free memory that is no longer in use due to an oversight or error. A memory leak does not refer to the physical disappearance of memory, butAfter the application allocates a certain segment of memory, due to a design error, it loses control of the segment of memory, resulting in a waste of memory

4.1 Hazards of memory leaks

Memory leaks occur in long-running programs, such as the operating system, background services, etc., and memory leaks will
cause slower and slower responses, and eventually freeze.

4.2 Classification of memory leaks

In C/C++ programs, we generally only care about two aspects of memory leaks:

  • Heap memory leak
    refers to a piece of memory allocated from the heap through malloc / calloc / realloc / new, etc., as needed during program execution, and must be deleted by calling the corresponding free or delete after it is used up. Assuming that the design error of the program causes this part of the memory to not be released, then this part of the space will no longer be used in the future, and a Heap Leak will occur.
  • System resource leakage
    refers to the use of resources allocated by the system, such as sockets, file descriptors, pipes, etc., which are not released by corresponding functions, resulting in waste of system resources, which can seriously reduce system performance and lead to unstable system execution.

4.3 How to detect memory leaks

  • Memory leak detection under linux: Several memory leak detection tools under linux
  • Using third-party tools under Windows: VLD tool description
  • Other Tools: Memory Leak Tools Comparison

4.4 How to avoid memory leaks

  1. Good design specifications in the early stage of the project, develop good coding specifications, and remember to release the matching memory space. ps: This ideal state. But if you encounter an exception, even if you pay attention to the release, there may still be problems. It is guaranteed that the next smart pointer is needed to manage.
  2. Use RAII ideas or smart pointers to manage resources.
  3. Some internal company specifications use internally implemented private memory management libraries. This library comes with options for memory leak detection.
  4. Something went wrong using the memory leak tool to detect. ps: However, many tools are not reliable enough, or are expensive.

To sum up:
memory leaks are very common, and the solutions are divided into two types: 1. Precautionary type. such as smart pointers. 2. Post-mortem error checking. such as leak detection tools

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324163830&siteId=291194637