文章目录
一、动态内存分配
二、malloc和free
三、calloc 和 realloc
3.1 calloc
3.2 realloc
四、常见的动态内存错误
4.1 对 NUll指针的解引用操作
4.2 对动态开辟空间的越界访问
4.3 对非动态开辟内存使用free释放
4.4 使用 free 释放一块动态开辟内存的一部分
4.5 对同一块动态内存多次释放
4.6 动态开辟内存忘记释放(内存泄漏)
五、柔性数组
5.1柔性数组
5.2 柔性数组的使用
六、总结C/C++中程序内存区域划分
一、动态内存分配
在之前你的学习中我们掌握的内存开辟方式有:
- int val = 20;//在栈空间上开辟四个字节
- char arr[10] = {0};//在栈空间上开辟10个字节的连续空间
二、malloc和free

int main()
{//申请10个整型的空间//int* p = (int*)malloc(10*sizeof(int));if (p == NULL){//空间开辟失败perror("malloc");return 1;}//可以使用这个40个字节的int i = 0;for (i = 0; i < 10; i++){*(p + i) = i + 1;}//释放free(p);p = NULL;//return 0;
}
- malloc 申请的空间和数组的空间有什么区别:
(1)动态内存的大小是可以调整
(2)开辟的空间的位置不一样
- 内存:栈区、堆区、静态区...
- 栈区:局部变量(比如数组)、形式参数、...
- 堆区:动态内存(malloc 、free 、calloc 、realloc 、...)
- 静态区:全局变量、static 修饰的静态变量
- 当 p 释放后,p 指向的空间不属于当前程序,但是还是找到这个空间,说明 p 是野指针!(如果不释放的话,程序结束的时候也会被操作系统自动回收。)
- malloc 和 free 最好成对使用
三、calloc 和 realloc
3.1 calloc

#include <stdio.h>
#include <stdlib.h>int main()
{//申请10个整型的空间//int* p = (int*)calloc(10,sizeof(int));if (p == NULL){//空间开辟失败perror("calloc");return 1;}//可以使用这个40个字节的int i = 0;for (i = 0; i < 10; i++){printf("%d", * (p + i) );}//释放free(p);p = NULL;//return 0;
}
3.2 realloc

- realloc函数在调整空间的时候,有2种情况
情况1:原有空间之后有⾜够⼤的空间,要扩展内存就直接原有内存之后直接追加空间,原来空间 的数据不发⽣变化。
情况2:原有空间之后没有⾜够⼤的空间,realloc函数直接在内存的堆区找一块新的满足大小的空 间,将就的数据,拷到新的空间,释放旧的空间,返回新的地址。
下面的图可以更直观的解释:
四、常见的动态内存错误
4.1 对 NUll指针的解引用操作
void test(){int *p = (int *)malloc(10*sizeof(int));*p = 20;//如果p的值是NULL,就会有问题free(p);}
4.2 对动态开辟空间的越界访问
void test(){int i = 0;int *p = (int *)malloc(10*sizeof(int));if(NULL == p){perror(“malloc”);return 1;}for(i=0; i<40; i++){*(p+i) = i;//当i大于等于10的时候越界访问}free(p);}
4.3 对非动态开辟内存使用free释放
void test(){int a = 10;//(不是动态内存)int *p = &a;free(p);}
4.4 使用 free 释放一块动态开辟内存的一部分
void test(){int *p = (int *)malloc(100);p++;free(p);//p不再指向动态内存的起始位置}
4.5 对同一块动态内存多次释放
void test(){int *p = (int *)malloc(100);free(p);free(p);//重复释放}
4.6 动态开辟内存忘记释放(内存泄漏)
void test()
{int flag = 1;int*p = (int*)malloc(100);if (p == NULL){//return;}//使用if (flag)return;//此处 flag 为 1 已经返回主函数中,没有释放 p free(p);p = NULL;
}int main()
{test();return 0;
}
(动态内存管理是一把双刃剑,提供灵活的内存管理方式的同时会带来风险!)
五、柔性数组
5.1柔性数组
比如:
#include <stdio.h>
#include <stdlib.h>struct S
{int n;//4int arr[];
};int main()
{printf("%d", sizeof(struct S));return 0;}
输出结果为 4
5.2 柔性数组的使用
#include <stdio.h>
#include <stdlib.h>struct S
{int n;//4int arr[];
};int main()
{struct S* ps = (struct S*)malloc(sizeof(struct S) + 20*sizeof(int));if(ps == NULL){perror("malloc()");return 1;}//使用这些空间ps->n = 20;int i = 0;for (i = 0; i < 20; i++){printf("%d ", ps->arr[i]);}return 0;}

- 这样柔性数组成员a,相当于获得了20个整型元素的连续空间。
六、总结C/C++中程序内存区域划分
