之前提到的指针的地址都是来源于对一个变量或者数组取地址,然后赋值于该指针。但是实际中,指针指向的内存地址都是动态申请到的。
内存模型
![]() |
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 - 大多数堆栈的地址申请是相向而行的,堆的地址越来越大;栈的地址越来越小 |
---|---|
int a = 0;
int b = 0;
int c = 0;
// 栈中申请
cout << &a << endl;
cout << &b << endl;
cout << &c << endl;
// 动态申请
int * p1 = (int*) malloc (4);
int * p2 = (int*) malloc (4);
int * p3 = (int*) malloc (4);
cout << p1 << endl;
cout << p2 << endl;
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!
C++中没有内存回收机制void free( void* ptr ) ;
Question:
```cpp void foo() { int p = (int ) malloc( sizeof(int)); return; } //memory leakp = (int *) malloc(4 * sizeof(int)); // 分配16个字节的内存给p // ... p = (int *) malloc(8 * sizeof(int)); // 第二次分配的地址把第一次的地址覆盖了 // 那么第一次分配的地址就会消失,无法找回,无法释放,浪费内存 // ... free (p);
// 函数中分配地址,但是没有释放就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个字节。但是该程序体量小,程序不做回收的话,在程序终止后,操作系统会将该程序的所有内存都回收掉,所以该程序不会出现错误;但是如果体量大的程序,只申请内存而不手动释放,那么你的程序会占用超多内存,甚至耗尽内存,程序崩溃。