[C++] C/C++ memory distribution [Detailed explanation of C/C++ memory management methods and the relationship between new/delete, operator new/operator delete, and malloc/free to explain the memory leak problem]

C/C++ memory distribution




1. C/C++ memory distribution

(1) Compare global variables

// 对比全局变量
//**链接属性**的区别:
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";
 const 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);
}

Differences between link attributes:

int globalVar; // All files can be used
static int staticGlobalVar; // Can only be used inthe current file
static int staticVar; // Can only be used in the scope

Can be used throughout the life cycle


Insert image description here

Insert image description here
Insert image description here



Summarize

Insert image description here

【illustrate】

  1. :Screaming again – Non-static Local change amount/Function number/Returnetc.< a i=9>临时阶变,栈是向下增长的.

    The function creates a stack frame and stores temporary variables

  2. Memory mapping segment": It is an efficient I/O mapping method, used to load a shared dynamic memory library. Users can use the system interface to create shared shared memory and run processes communication. (If you haven’t learned this in the Linux course, you just need to understand it now)

  3. Heap: used when the program is runningdynamic memory allocation, the heap is< a i=4> can grow.

  4. Several steps 【Jingping district】:Zen储All stations number stationtranquil number station.

  5. Code segment [Constant area]:Executable code, Read-only data (including constants)

    Constant area, modification will result in an error
    The constant area stores binary code (can only be understood by the instruction CPU)

  6. The code we typed (just a file) is stored in disk



*char2

char2 array name => The address of the first element, *char2 (*address=>) is on the stack

const char* pChar3 [The const here modifies the content *p pointed to by the pointer, not p itself]

The content of the char2 array is in the constant area. Copy the content to the space opened by the array on the stack.

The essence of the definition of [] square brackets is to copy the string content in the constant area.

pChar3 is a pointer variable (temporary variable is stored on the stack). In fact, the address should be stored.

Constant variables: variables with constant attributes

Literal: The value of a constant. By default, the literal will be type-identified for easy transmission.



2. C++ memory management method

Preface: Dynamic memory management methods in C language: malloc/calloc/realloc/free

void Test ()
{
    
    
int* p1 = (int*) malloc(sizeof(int));
free(p1);
// 1.malloc/calloc/realloc的区别是什么?
int* p2 = (int*)calloc(4, sizeof (int));
int* p3 = (int*)realloc(p2, sizeof(int)*10);
// 这里需要free(p2)吗?
free(p3 );
}

[Interview questions]

  1. What is the difference between malloc/calloc/realloc?

  2. The implementation principle of malloc? Principle of malloc implementation in glibc


The C language memory management method can continue to be used in C++, but there are some places where it cannot be helped. For example:

  1. It is not easy to initialize after malloc. Private member variables cannot be initialized.
    Insert image description here
    And it is more troublesome to use.

  2. The constructor is automatically called when instantiating an object and cannot be called explicitly.malloc is not convenient to solve the initialization problem of dynamically applied custom type objects



ThereforeC++ proposed its ownmemory management method: Performed through new and delete operators< a i=9>Dynamic Memory Management.

1. C++ memory management method

(1) New/delete operation built-in type

void Test()
{
    
    
  // 动态申请一个int类型的空间
  int* ptr4 = new int;
  
  // 动态申请一个int类型的空间并初始化为10
  int* ptr5 = new int(10);
  
  // 动态申请10个int类型的空间
  int* ptr6 = new int[10];
  delete ptr4;
  delete ptr5;
  delete[] ptr6;   //开了多个内存的 new[],也要对应的delete也要加上[]
}

malloc:single open space

(1)new : new + 类型( 开辟的类型 )+ [] ([]代表开辟空间的数量 ) +{}( 初始化的的内容 )

Syntax: new + type (opened type) + [] (number of objects) + {} (initialized content)

  • Type: Just enter the data type to be developed, no forced conversion is required.
  • [ ]Automatically recognize the previously entered type and automatically calculate the sizeof size.


initialization

  1. Single dataInitialize

new + type +()

  1. Multiple dataInitialize

new + type + [] + {} ( {} put multiple values ​​to be used for initialization)

Insert image description here
The following values ​​are initialized to 0 by default.



(2) delete calls the destructor + releases space

To match new


Insert image description here



For built-in types, there is no difference between new/delete and malloc/free at the bottom level, except for the usage, which is different from the checking method.

(3) The biggest difference between new/delete and malloc/free is the operation of custom types

// new和delete操作自定义类型
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;
}
  • For objects ofbuilt-in type application and release

    new and malloc (malloc will return nullptr if it fails, check whether it is nullptr) (new fails: throws exception)

    throws bad_alloc type exception .
    Insert image description here
    Memory allocation failed.

    Insert image description here
    cout is an automatic type recognition address will be recognized as a string , and it will stop when it encounters \0.
    try catch If an error occurs, it will jump directly to the place where the error occurred


There is no difference except usage

  • Forcustom types

    new/delete for[custom type]
    exceptopen space, and alsocall the constructor and destructor

    Malloc/free does not.

Theessence of open space + call structure Function initialization:new

  1. open space = malloc
  2. Call the constructor and initialize

Explicitly call the constructor A* p7=new A(1);

delete:Call destructor + release space


There is no concept of constructor in the C language library .



(2) Operator new and operator delete functions (important points will be explained)

(1) operator new and operator delete functions (key points)

  1. new/delete is performed by the userdynamic memory application and releaseOperator; operator new / operator delete is provided by the system The global function .

  2. new calls "operator new global function" at the bottom layer to apply for space, delete uses operator delete global function at the bottom layer to release space a> .

  3. operator new: This function actually applies for space through malloc, when malloc applies for space successfully. Return directly;application space
    fails, try to implement insufficient space countermeasures
    , if the countermeasures are set by the user, then Continue to apply, otherwise a bad_alloc type exception will be thrown.
    Insert image description here
    Memory allocation failed

  4. operator delete: This function ultimately releases space through free


/*
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 ); //operator delete: 该函数最终是通过free来释放空间的
     __FINALLY
         _munlock(_HEAP_LOCK);  /* release other threads */
     __END_TRY_FINALLY
     return;
}
/*
free的实现
*/
#define   free(p)               _free_dbg(p, _NORMAL_BLOCK)  //free的实现


(3) Summary of implementation principles of new and delete

Difference 1: C dynamic memory management is very friendly to built-in types, but custom types cannot access private permissions in classes (newly added in C++) => new: open up space + automatically call constructor


(1) For built-in types

Same:
If you apply for built-in type Space, new and malloc, delete and free are basically similar.

The differences are:

  1. new/delete applies for and releases space for a single element, < a i=4>new[] and delete[] apply for continuous space.
  2. Andnew will throw an exception when it fails to apply for space, malloc will return NULL.

(2) Custom type

1. Principle of new

  1. Call operator new(global) functionApply for spaceActually operator new calls malloc]
  2. Executeconstructor after the requested space to complete the construction of the object

2. Principle of delete

  1. Execute the destructor on the space to complete the cleanup of resources in the object
  2. Call operator delete (global) functionRelease the object's spaceActually operator delete and then call free

3. Principle of new T[N]

  1. Call operator new[] function, in operator new[]【 actually call operator new function to complete N pairs
    Application for Xiang Space
    ]
  2. Execute the constructor on the requested spaceN times

4. Principle of delete[]

  1. Execute the destructor on the released object spaceN times to complete the cleanup of resources in N objects
  2. Calloperator delete[] to release space, [ actually calls operator delete in operator delete[] to release space

Difference 2: There is no need to calculate the size of the opened space based on the type of data stored. There is no need to force the return type, making it much easier to use.


Difference three: new will throw an exception throw (keyword) => try catch If an error occurs, it will jump directly to the place where the error occurred. If an exception occurs, it will jump directly to the catch place.


(4) Summary

new —> Call operator new global function —> malloc

  1. new Constructor opening space + initialization

  2. new/delete关键字.

  3. operate new/operate delete corresponds to malloc/free, which is the function . If malloc is wrong in c, it will return 0/null pointer nullptr. new object-oriented fails and cannot be processed with return value => encapsulates malloc and throws an exception after failure .

  4. operate new is not an overload of new, but a global function, is a package of malloc

  5. delete is used in conjunction with new. new is paired with delete, and new[ N ] is paired with delete [ ].

    The first line is the number of allocated arrays, Each custom type has 4 more bytes, is left to delete[]

    does not require the number of arrays to be given in [ ]. Subtract 4 from p3 to find the number of previous arrays, destruct each array, and then free the space originally opened by the entire object.
    Only by [] can we find 4 bytes forward. can we completely free the opened array. Only delete p4 can only release from the address pointed to by p4, so the operation of opening 4 bytes forward will not be performed, new[] Just want it.

    If new[ N ] is paired with delete, it will appear:
    delete p4 thencan only start releasing from the address pointed to by p4 a>, so the operation of opening 4 bytes forward will not be performed, which will leak the 4 bytes of memory space used by the previous custom type to store the number of arrays.

    Therefore, new/delete, new[]/delete[] malloc/free must be used in pairs, otherwise the result will be undefined.



(4) Positioning new expression (placement-new) (understand)

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

  • Use format:
    new (place_address) type ornew (place_address) type(initializer-list )
    place_address must be a pointer, initializer-list is the initializer of type List

  • Usage scenarios:
    In practice, positioning new expressions is generally combined with memory pool [memory pool] Apply a little more at a time]Use. Because the memory allocated by the memory pool is not initialized, so if it is an object of custom type< a i=9>, you need to use the definition expression of new to display and call the constructor for initialization, which is used in conjunction with the memory pool to apply for object space.

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


// 定位new/replacement new
int main()
{
    
    
 // p1现在指向的只不过是与A对象相同大小的一段空间,还不能算是一个对象,因为构造函数没有执行
 A* p1 = (A*)malloc(sizeof(A));
 new(p1)A;  // 注意:如果A类的构造函数有参数时,此处需要传参
 p1->~A();
 free(p1);


 A* p2 = (A*)operator new(sizeof(A));
 new(p2)A(10);
 p2->~A();
 operator delete(p2);
  return 0;
}


(5) Common interview questions

【1】 The difference between malloc/free and new/delete


malloc/free和new/delete

The common ground is: they all apply for space from the heap, and < a i=4>Requires manual release by the user.

The differences are:

  1. mallocsumfreeherefunctionnewdeletecorrect Operation mark

  2. The space requested by malloc will not be initialized,new can be initialized

  3. When malloc applies for space, needs to manually calculate the space size and pass it , < a i=4>new Just followed by the type of space, if it is Multiple objects, just specify the number of objects in []

  4. The return value of malloc is void*, in Type conversion is required when using it, new does not need to be used, because new is followed by the type of space

  5. When malloc fails to apply for space, returns NULL, so You must check for null when using it; new does not need to, butnew needs to catch exceptions

  6. When applying for a custom type object, malloc/free will only open up space and will not be called Constructor and destructor;

    Andnew will call the constructor to complete the initialization of the object after applying for space c Dynamic memory management is very friendly to built-in types, but custom types cannot access private permissions in classes (newly added in C++) => new
    [

    Before delete releases the space will call the destructor to complete the cleanup of resources in the space



2. Memory leak

(Memory leaks will be mentioned later in smart pointers)

(1) What is a memory leak?

What is a memory leak: A memory leak occurs due tonegligence or error Causesa situation where the program fails to release memory that is no longer used. Memory leak does not refer to the physical disappearance of memory, but after the application allocates a certain section of memory, because The design error caused the control of this memory segment, resulting in waste of memory.



(2) The dangers of memory leaks

Hazards of memory leaks: Memory leaks in long-running programs, such as operating systems, background services, etc., have a great impact.
Memory leaks will cause slower and slower responses. , and finally got stuck.

void MemoryLeaks()
{
    
    
   // 1.内存申请了忘记释放
  int* p1 = (int*)malloc(sizeof(int));
  int* p2 = new int;
  
  // 2.异常安全问题
  int* p3 = new int[10];
  
  Func(); // 这里Func函数抛异常导致 delete[] p3未执行,p3没被释放.
  
  delete[] p3;
}


(3) Memory leak classification (understanding)

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

  • Heap leak

    Heap memory refers to the allocation according to needs during program execution throughmalloc / calloc / realloc / newetc.A piece of memory allocated in the heap, must be deleted by calling the corresponding free or delete after use .
    Assuming that the program design error causes this part of the memory to not be released, then this part of the space will no longer be used, and Heap Leak.

  • System resource leak

    refers to the program using the resources allocated by the system, for example Sockets, file descriptors, pipes, etc. are not released using the corresponding functions, resulting in a waste of system resources, which can seriously lead to a reduction in system performance and system Unstable execution.



(4) How to detect memory leaks (understand)

Under VS, you can use the **_CrtDumpMemoryLeaks()** function provided by the Windows operating system for simple detection. This
function only reports The approximate number of bytes was leaked, there is no other more accurate location information.

int main()
{
    
    
 int* p = new int[10];
 // 将该函数放在main函数之后,每次程序退出的时候就会检测是否存在内存泄漏
 _CrtDumpMemoryLeaks();
 return 0;
}


// 程序退出后,在输出窗口中可以检测到泄漏了多少字节,但是没有具体的位置
Detected memory leaks!
Dumping objects ->
{
    
    79} normal block at 0x00EC5FB8, 40 bytes long.
Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

So be careful when writing code, especiallydynamic memory operations. Be sure to remember Release. But in some cases, it is always difficult to prevent it. You can simply use the above method to quickly locate it. Ifthe project is relatively large and there are many memory leak locations, which are difficult to check, usually use a third party Memory leak detection tools handle's.



(5) How to avoid memory leaks

  1. Pre-project periodGood design standards, developgood coding standards< a i=4>, The memory space applied for will be released accordingly. . ps: This is the ideal state. But if you encounter an exception, even if you pay attention to the release, problems may still occur. The next smart pointer is needed to manage it to ensure it.
  2. For RAII Thought Someone Intellectual Guidance The next management resource .
  3. Some companies internally standardize the use of internally implemented private memory management libraries. This library comes with memory leak detection function options.
  4. Something went wrong. Use a memory leak tool to detect. ps:However, many tools are unreliable or expensive.

To summarize:
Memory leaks are very common. The solutions are divided into two types: 1. < /span>. Leak Detection Tool. Such as Post-error checking type etc. 2. Smart pointer. Such as Preventive type

Guess you like

Origin blog.csdn.net/NiNi_suanfa/article/details/134564015