之前提到的指针的地址都是来源于对一个变量或者数组取地址,然后赋值于该指针。但是实际中,指针指向的内存地址都是动态申请到的。
    内存模型

    image.png The address space of a program contains several data segments.
    - Code: executable code
    - Data: initialized static variables
    - BSS: uninitialized static data including variables and constants
    - Heap堆: dynamically allocated memory
    - Stack栈: local variables, call stack
    - 大多数堆栈的地址申请是相向而行的,堆的地址越来越大;栈的地址越来越小
    1. int a = 0;
    2. int b = 0;
    3. int c = 0;
    4. // 栈中申请
    5. cout << &a << endl;
    6. cout << &b << endl;
    7. cout << &c << endl;
    8. // 动态申请
    9. int * p1 = (int*) malloc (4);
    10. int * p2 = (int*) malloc (4);
    11. int * p3 = (int*) malloc (4);
    12. cout << p1 << endl;
    13. cout << p2 << endl;
    14. cout << p3 << endl;

    But different CPU architectures may be different

    ARM64 X86_64
    0x16cf7b648
    0x16cf7b644
    0x16cf7b640
    0x145606790
    0x1456067a0
    0x1456067b0
    0x3064676e8
    0x3064676e4
    0x3064676e0
    0x7ff835c059c0
    0x7ff835c059d0
    0x7ff835c059e0
    栈中申请的内存地址是逐渐减小的,而动态申请的内存地址逐渐增大,而且虽然分配了4个字节,但是实际上占用16个字节,16位对齐。 但是X86处理器的栈内存地址特别小,动态申请的内存地址特别大,所以不同处理器,内存分配规则不同,stack地址是逼近0的。

    Memory allocation
    Allocate size bytes of uninitialized storage.

    void* malloc( size_t size )
    

    Allocate 4 bytes and convert the pointer to (int *) explicitly.

    int * p1 = (int*) malloc (4);
    

    Question:

    int * p1 = (int*) malloc (3);
    

    为p1申请了三个字节,但是malloc动态分配会16位对齐,不会分配给别的程序使用,使用第四个字节也不会有问题,但是编程习惯不好。

    Memory deallocation 内存释放

    • The dynamically allocated memory must be deallocated explicitly!
      void free( void* ptr ) ;
      
      C++中没有内存回收机制
      Question:
      p = (int *) malloc(4 * sizeof(int));  // 分配16个字节的内存给p
      // ...
      p = (int *) malloc(8 * sizeof(int));  // 第二次分配的地址把第一次的地址覆盖了
      // 那么第一次分配的地址就会消失,无法找回,无法释放,浪费内存
      // ...
      free (p);
      
      ```cpp void foo() { int p = (int ) malloc( sizeof(int)); return; } //memory leak

    // 函数中分配地址,但是没有释放就return了, // p的作用域在函数内部,return之后,p就消失了,这段内存也无法回收了 // 可以return 该指针,在函数外部释放,也是可以的

    :::warning
    Memory leak:
    
    - No variable to keep the first address. The memory management system will not deallocate it automatically. Waste of memory!
    :::
    :::info
    每次申请内存,一定要记住该内存地址,然后不用之后,就要释放;<br />内存地址在哪里申请就在哪里释放
    :::
    ```cpp
    #include <stdio.h>
    #include <stdlib.h>
    
    void foo()
    {
        int *p = (int *)malloc(sizeof(int));
        return;
    } //memory leak
    
    int main()
    {
        int *p = NULL;
    
        p = (int *)malloc(4 * sizeof(int));
        // some statements
        p = (int *)malloc(8 * sizeof(int));
        // some statements
        free(p);
        // the first memory will not be freed
    
        for (int i = 0; i < 1024; i++)
        {
            p = (int *)malloc(1024 * 1024 * 1024);
        }
        printf("End\n");
    
        return 0;
    }
    

    该程序,调用一次浪费4个字节。但是该程序体量小,程序不做回收的话,在程序终止后,操作系统会将该程序的所有内存都回收掉,所以该程序不会出现错误;但是如果体量大的程序,只申请内存而不手动释放,那么你的程序会占用超多内存,甚至耗尽内存,程序崩溃。