C语言 动态内存分配
C语言 动态内存分配
- 一、动态内存分配函数
- 1.1 malloc和free函数
- 1.2 calloc函数
- 1.3 realloc函数
- 二、常见的动态内存错误
- 2.1 对NULL指针进行解引用操作
- 2.2 动态内存分配空间的越界访问
- 2.3 对非动态内存分配的空间free释放
- 2.4 对动态内存分配的空间的一部分free释放
- 2.5 对已经free的动态内存分配空间访问或再次free
- 2.6 内存泄漏
前言:之前学习了数组,数组的元素储存在内存中连续位置。在声明数组时必须要指定数组的元素个数,即数组空间大小在声明时已经确定了。但是需存放的元素个数常常在运行时才能知道(取决于输入的数据)。这会有几个缺点: 1. 当输入元素个数大于数组声明的元素个数时会带来意想不到错误 2. 当输入元素个数小于数组声明的元素个数时会带来内存空间的浪费 3. 数组大小不能动态调整。
C语言提供了相关的动态内存分配函数,需要多大内存空间就分配多大内存空间,并且可以动态调整已分配的内存空间大小
一、动态内存分配函数
使用下面相关动态内存函数需要引用头文件 <stdlib.h>
1.1 malloc和free函数
malloc函数功能:
向内存申请指定大小的连续内存空间,申请成功返回该空间起始地址,申请失败返回NULL指针
库函数malloc声明
void* malloc (size_t size);
返回值:申请成功返回该空间起始地址,申请失败返回NULL指针,因为不知道申请的空间要存放什么类型数据所以返回void*类型
size: 申请分配的内存大小,单位为字节
注意:
1. malloc返回值有可能是NULL指针,使用前需要检查
2. malloc申请的空间并没有被初始化
free函数功能:
释放申请的动态内存分配的空间(即malloc、calloc、realloc函数申请的空间)
库函数free声明
void free (void* ptr);
ptr : 指向先前用malloc、calloc或realloc分配的内存块的指针
注意:
1.如果 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的
2. 如果ptr 是NULL指针,则函数什么事都不做
3. 只会释放ptr指向空间的值,但ptr本身不会被置空
#include <stdio.h>
#include <stdlib.h>int main()
{//申请10个int类型大小空间,10 * sizeof(int)相对于sizeof(40)更具有移植性//由于malloc返回值为void*类型,所以强制类型转换为int*类型int* p = (int*)malloc(10 * sizeof(int));if (p == NULL) //空间申请失败则退出{return -1; }int i = 0;for (i = 0; i < 10; i++) //打印这10个元素{printf("%d ", *(p + i));}printf("\n");for (i = 0; i < 10; i++) //对数组元素赋值{*(p + i) = i;}for (i = 0; i < 10; i++) //打印这10个元素{printf("%d ", *(p + i));}printf("\n");free(p); //释放p所指向动态内存分配的空间p = NULL;//将p置为NULL指针,防止访问一个已释放的空间return 0;
}
输出
-842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451
0 1 2 3 4 5 6 7 8 9
1.2 calloc函数
calloc函数功能:
calloc函数与malloc函数功能一样,区别主要在于calloc会对分配的空间初始化为0,另外它们请求内存大小的方式不同
库函数calloc声明
void* calloc (size_t num, size_t size);
返回值:申请成功返回该空间起始地址,申请失败返回NULL指针,因为不知道申请的空间要存放什么类型数据所以返回void*类型
num:元素个数
size: 元素大小
申请内存空间大小=num*size
#include <stdio.h>
#include <stdlib.h>int main()
{int* p = (int*)calloc(10,sizeof(int));if (p == NULL) //空间申请失败则退出{return -1;}int i = 0;for (i = 0; i < 10; i++) //打印这10个元素{printf("%d ", *(p + i));}printf("\n");for (i = 0; i < 10; i++) //对数组元素赋值{*(p + i) = i;}for (i = 0; i < 10; i++) //打印这10个元素{printf("%d ", *(p + i));}printf("\n");free(p); //释放p所指向动态内存分配的空间p = NULL;//将p置为NULL指针,防止访问一个已释放的空间return 0;
}
输出
0 0 0 0 0 0 0 0 0 0
0 1 2 3 4 5 6 7 8 9
使用malloc还是calloc函数取决是否要对动态内存分配的空间初始化
1.3 realloc函数
realloc函数功能:
realloc对动态内存空间大小进行扩大或缩小
库函数realloc声明
void* realloc (void* ptr, size_t size);
返回值:返回调整后空间的起始地址,调整失败返回NULL指针
ptr:指向先前用malloc、calloc或realloc分配的内存块的指针
size:动态内存空间新大小,单位为字节
#include <stdio.h>
#include <stdlib.h>int main()
{int* p = (int*)malloc(10 * sizeof(int));if (p == NULL) //空间申请失败则退出{return -1;}int i = 0;for (i = 0; i < 10; i++) //对数组元素赋值{*(p + i) = i;}int* ptr = realloc(p, 20 * sizeof(int)); //对动态内存大小进行调整if (ptr == NULL) //调整失败并不影响原本p指向空间{printf("空间调整失败\n");}else{p = ptr; //调整成功,p指向调整后空间起始地址ptr = NULL;for (i = 10; i < 20; i++) //对数组元素赋值{*(p + i) = i;}for (i = 0; i < 20; i++) //打印数组元素{printf("%d ", *(p + i));}}free(p); //释放p所指向动态内存分配的空间p = NULL;//将p置为NULL指针,防止访问一个已释放的空间return 0;
}
输出
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
二、常见的动态内存错误
2.1 对NULL指针进行解引用操作
#include <stdio.h>
#include <stdlib.h>int main()
{int* p = (int*)malloc(100000000000000000 * sizeof(int));*p = 10; //没有对p是否非NULL检查return 0;
}
申请动态内存分配失败,p为NULL指针,对p解引用修改存储的值会错误
2.2 动态内存分配空间的越界访问
#include <stdio.h>
#include <stdlib.h>int main()
{int* p = (int*)malloc(10 * sizeof(int));if (p == NULL){return -1;}int i = 0;for (i = 0; i <= 10; i++){*(p+i) = i;}free(p);p = NULL;return 0;
}
当i=10,*(p+i)越界访问了
2.3 对非动态内存分配的空间free释放
#include <stdio.h>
#include <stdlib.h>int main()
{int i = 10;int* p = &i;free(p);p = NULL;return 0;
}
p指向空间不是动态内存分配的空间
2.4 对动态内存分配的空间的一部分free释放
#include <stdio.h>
#include <stdlib.h>int main()
{int* p = (int*)malloc(10 * sizeof(int));if (p == NULL){return -1;}free(p+5);p = NULL;return 0;
}
p+5指向空间是动态内存分配的空间的一部分
2.5 对已经free的动态内存分配空间访问或再次free
#include <stdio.h>
#include <stdlib.h>int main()
{int* p = (int*)malloc(10 * sizeof(int));free(p);*p = 10; //对已经free的动态内存分配空间访问free(p);//对动态内存分配空间多次free释放p = NULL;return 0;
}
2.6 内存泄漏
当申请的动态内存空间不需要时应该被释放,这样可以重新分配使用。申请的空间在使用完毕后不free释放将引起内存泄漏。内存泄漏将一点点榨干可用内存,最终导致系统崩溃
#include <stdio.h>
#include <stdlib.h>
void test()
{int* p = (int*)malloc(10*sizeof(int));
}
int main()
{while(1){test();//业务处理,满足条件则退出while循环}return 0;
}
当业务处理没有满足条件则while为死循环,每次循环都会申请内存空间,最终将系统崩溃
C语言 动态内存分配相关推荐
- c语言动态内存分配数组,【C】动态内存分配
## 动态内存分配的意义 C语言中的一切操作都是基于内存的 变量和数组都是内存的别名 内存分配由编译器在编译期间决定 定义数组的时候必须指定数组长度 数组长度是在编译期就必须确定的需求: 程序在运行过 ...
- linux 在指定区域分配内存 c语言,C语言动态内存分配:(一)malloc/free的实现及malloc实际分配/释放的内存...
一.malloc/free概述 malloc是在C语言中用于在程序运行时在堆中进行动态内存分配的库函数.free是进行内存释放的库函数. 1.函数原型 #include void *malloc( s ...
- C语言动态内存分配:(一)malloc/free的实现及malloc实际分配/释放的内存
最新个人博客 shankusu.me 以下内容转载或参考或引用自 https://blog.csdn.net/zxx910509/article/details/62881131 一.malloc/f ...
- C语言动态内存分配详解
文章目录 前言 一.为什么存在动态内存分配 1.已掌握的内存开辟方式 2.上述开辟空间方式的特点 3.为什么存在动态内存分配 二.动态内存函数的介绍 1.malloc 2.free 3.calloc ...
- C语言:动态内存分配+经典面试题
前言: 通常,我们在栈空间开辟的内存都是固定的,这是十分不方便使用的.为了更加灵活的分配和使用内存,我们要学习C语言中一些常用的与内存分配相关联的函数.顺便,我们会补充数组中柔性数组的知识. 内存分区 ...
- 浅谈C语言动态内存分配及柔性数组
文章目录 前言 1.动态内存的简单介绍 1.动态内存分配是什么? 2.为什么存在动态内存分配? 3.动态内存分配具体方法 1.动态内存函数 2.动态内存注意事项 2.经典面试题分析 3.C/C++程序 ...
- C语言动态内存分配函数
目录 1.malloc() 2.free() 3.calloc() 4.realloc() 5.小结 在C中我们开辟内存空间有两种方式 : 1.静态开辟内存 : 例如: int a; int b[10 ...
- C语言-动态内存分配总结
目录 1 malloc 2 calloc 区别联系 3 memset 4 realloc 1 malloc void *malloc( unsigned int num_bytes) 分配长度为num ...
- C语言——动态内存分配
内存分配函数: malloc函数--分配内存块,但是不对其进行初始化. calloc函数--分配内存块,并且对其进行初始化(清0). realloc函数--调整先前分配的内存块大小. 函数原型: vo ...
- 不允许指针指向不完整的类类型_8.7 C语言动态内存分配与指向它的指针变量
01什么是内存的动态分配 1.全局变量是分配在内存中的静态存储区的,非静态的局部变量(包括形参)是分配在内存中的动态存储区的,这个存储区是一个"栈"的区域. 2.C语言允许建立内存 ...
最新文章
- WMI技术介绍和应用——查询正在运行的线程信息
- 清华刘洋:论文写作,信息为表,逻辑为骨,思想为心
- 用1天快速上手org-mode(windows系统)
- Java中switch都可以支持哪些数据类型
- elasticsearch 2.2+ index.codec: best_compression启用压缩
- 2.4.2 死锁的处理策略-预防死锁
- c# wpf listbox 高度_WPF快速入门系列(1)——WPF布局概览
- 分布式一致性协议Raft原理与实例
- Java语言中的注释有哪些
- 与传统的计算机硬件系统相比,计算机一级名词解释
- linux内存分配器类型,内核早期内存分配器:memblock
- Nginx学习_狂神
- [7] ADB 模拟按键/输入
- PHP 开发者该知道的 5 个 Composer 小技巧
- IC卡、ID卡、CPU卡、RFID、NFC大致区分一览表
- ORACLE清空数据库中所有表中的数据
- 银联支付接口申请-手机控件支付
- ​​欧洲能源危机日益严重,这个冬天到底会有多 “冷” ?
- 再生龙备份linux文件多大,使用再生龙Clonezilla备份还原Linux系统
- 【揭秘恒大老总许家印】迄今为止最深度、全面的。
热门文章
- 如何将微信电脑图片dat格式文件转换为jpg格式
- 手机常识——查看手机曾经连接过的wifi密码
- 量化交易——PEG策略
- Matlab突然打不开,运行后一闪就消失了,任务管理器也没有的解决办法
- GoodUP:智协云店通+BitCOO的4WiN全球互贸链 | 翼次元空间
- linux中无损gpt转mbr,如何快速实现免重装无损磁盘MBR转GPT?
- 爬虫python是什么意思_python爬虫是什么? 【黑马程序员】
- CAD如何绘制带有弧形的箭头
- cad多段线画圆弧方向_怎样在cad中利用多线画圆弧
- 熊出没机器人光头强_《熊出没》五大兵器,天才威与光头强的战斗机器人谁更厉害?...