文章目录
动态内存分配(C/C++)
1. C/C++程序内存分配的几个区域
-
栈区 (stack): 在执行程序时, 函数内局部变量的存储单元都可以创建在栈上, 函数执行结束时这些存储单元自动被释放. 栈内存的分配运算内置于处理的指令集中, 效率高, 但是分配的内存容量有限.
-
堆区(heap): 由程序员自己分配和释放, 分配方式类似于链表. 如果程序员没有释放, 程序结束时可能由os回收.
-
静态区(static): 存放全局变量, 静态数据. 程序结束后由系统释放.
2. 动态内存分配的常用函数
2.1 malloc和free
int main()
{
int* p = (int*)malloc(10 * sizeof(int)); //开辟十个int大小的堆区空间
if (p == NULL) {
printf("%s\n", strerror(errno));
}
else {
printf("%s\n%s", "complete", "yeah");
for (int i = 0; i < 10; i++)
{
*(p + i) = i;
printf("%d ", *(p + i));
}
}
// 当申请的动态空间不使用时,应该还给操作系统
// 鼓励主动释放
free(p);
p = NULL;
return 0;
}
2.2 calloc
int main()
{
// calloc 每个元素默认值为0
int* p = (int*)calloc(10, sizeof(int));
//int* p = (int*)malloc(40);
cout << "第一次开辟的地址:" << p << endl;
if (p == NULL) {
cout << "开辟失败" << endl;
return 1;
//printf("%s\n", strerror(errno));
}
else
{
printf("%s\n%s\n", "complete", "yeah");
for (int i = 0; i < 10; i++)
{
*(p + i) = i;
printf("%d ", *(p + i));
}
}
cout << endl;
//假如四十个字节不能满足需求了,再开辟四十个
//此时需要弄一个临时指针
int new_number = 11;
//用新定义的指针来管理
int* ptr = (int*)realloc(p, new_number*sizeof(int));
if (ptr == NULL)
{
// 追加失败
cout << "追加内存失败" << endl;
return 2;
}
else {
p = ptr;
cout << "第二次开辟的空间:" << p << " 临时地址:" << ptr << endl;
int i = 0;
for (i = 0; i < new_number; i++)
{
//*(p2 + i) = i;
printf("%d ", *(p + i));
}
}
cout << endl;
free(p);
p = NULL;
cout << *ptr << endl;
return 0;
}
3. 动态内存分配的常见错误
-
对空指针NULL进行解引用操作
-
对开辟的空间进行越界操作
-
用free函数释放非动态空间的内存
-
使用free只释放了动态空间的一部分
补充: 柔性数组
定义: 结构体当中最后一个元素允许时未知大小的数组, 此时该元素(成员)被称为’柔性数组’成员.
struct Student {
int age;
int arr[]; //在结构体当中,此时可以是未知大小的,这个就是柔性数组
//int arr[0]; // 第二种表示方法
};