【动态内存】C语言动态内存使用常见错误及其避免方法(初学者避雷)
C语言动态内存使用常见错误及其避免方法(初学者动态内存避雷手册)
求个赞求个赞求个赞求个赞 谢谢
先赞后看好习惯 打字不容易,这都是很用心做的,希望得到支持你 大家的点赞和支持对于我来说是一种非常重要的动力 看完之后别忘记关注我哦!️️️
动态内存开辟常见错误
1.对NULL指针的解引用
2.越界访问
3.使用free释放非动态开辟的空间
4.使用free释放动态内存中的一部分
5.对同一块动态开辟的空间,多次释放
6.动态开辟的空间忘记释放-比较严重
文章目录
对空指针的非法解引用
一般来说,有一定基础的我们都不会故意解引用空指针,但是,我们在使用动态内存开辟的时候,可能会解引用到”无形“的空指针
int main()
{
int*p=(int*)malloc(10000000000000000000);
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = i;//err
}
return 0;
}
在上面这个代码中,看似没有什么问题。但是我们知道malloc函数是有可能开辟动态内存空间失败的,我们一口气开辟这么多字节的空间,我们堆上空间不够用了,malloc函数就会开辟失败,我们通过www.cplusplus.com网站搜索malloc函数我们可以知道,如果函数开辟失败,会返回空指针,那么这个时候,我们的p就是一个空指针,空指针怎么能解引用呢?
我们可以在for之前用一个perror()函数来查看我们的问题perror("main:");

为了避免在编写程序的时候遇到这个问题,我们可以用assert()断言后再使用该指针,或者使用if语句,当指针为真的时候再使用该指针
越界访问问题
int main()
{
int* p = (int*)malloc(10 * sizeof(int));
if (p == NULL)
{
return 1;
}
int i = 0;
//越界访问,我们只开辟了40个字节,不是四十个整型
for (i = 0; i < 40; i++)
{
*(p + i) = i;
}
free(p);
p = NULL;
return 0;
}
正如这个代码,我们必须知道malloc函数在堆上开辟的时候的单位是字节,而我们这里却要访问40个整型,也就是160个字节,这就越界访问了
每写一步我们思考清楚就可以避免这个问题。
使用free释放非动态开辟的空间
free只能用来释放堆上的动态开辟的空间,而不能释放栈上的空间,栈上的内存空间,在函数结束,程序结束都会自动释放的。
//3.使用free释放非动态开辟的空间
int main()
{
int arr[10] = { 0 };
int* p = arr;
free(p);//err
p = NULL;
return 0;
}
每写一步我们思考清楚就可以避免这个问题。
使用free释放动态内存中的一部分
释放了,但没完全释放
//4.使用free释放动态内存中的一部分
int main()
{
int* p = malloc(10 * sizeof(int));
if (p == NULL)
{
return 1;
}
int i = 0;
for (i = 0; i < 5; i++)
{
*p++ = i;//我的p不见了
}
free(p);//err
p = NULL;
return 0;
}
*在这个代码中,由p指针指向的动态内存开辟后,我们的p在后续操作中改变了它自己的值,这意味这什么?
这代表没东西再可以找到这块空间了,我们到时候free§只是free()掉了p后面的一些空间,那么p前面的空间呢?不管了?
所以如果p这个位置改变了,找不到了是一件很可怕的事情。
那么,我们如何避免呢?
如果在后续我们要操作p,我们一开始就要用另一个的指针变量来记录我一开始p的位置,最后free()这个记录起始位置的指针变量,这样就可以避免“free()了,但没完全free()的问题”
对同一块动态开辟的空间,多次释放的问题
//5.对同一块动态开辟的空间,多次释放
int main()
{
int* p = (int*)malloc(100);
//使用
//...
free(p);//万一一个在函数里面,没发现,就会出现这种情况
//
free(p);
return 0;
//所以这个时候,我们需要再free完,立刻把p置为空指针
//这样的话,第二次调用free()的时候,传空指针,什么事情都不会发生
}
看到这里,有些伙伴可能会问:我肯定不会两个free写在一起啊
这里其实只是比较明显而已,如果在函数里面,已经free了,后面又写了很多代码,最后想起来又free一次,这样就会出现这种问题了
为了避免这个问题,我们一定要主动地在free()之后,马上把我们的p置空:p=NULL;这样我们后面就算在free(),free()函数传NULL给它的时候,是不会有任何问题的。
动态开辟的空间忘记释放(比较严重的问题)
//6.动态开辟的空间忘记释放
void test()
{
int* p = (int*)malloc(100);
if (p == NULL)
{
return;
}
//使用
//忘记释放了
//
//
//
//当我们出函数的时候,p会自动释放,那没人可以找到那块在堆上的空间了
//如果return以后,就没有人可以找到p指向的空间了
//这样会造成内存泄露
}
int main()
{
test();
return 0;
}
我们在前面介绍部分释放这个问题的时候已经知道,不free()会造成内存泄漏
在这里,我来为大家总结一下堆上动态开辟的空间的两种释放方式
1.程序员代码主动释放,即调用free()函数
2.程序结束
在我们一开始使用动态内存的阶段,这个问题可能看似没那么严重,程序好像照样跑,反正泄露一点也没关系,程序结束它就自动释放了
但如果我们这是一个服务器的程序呢,24小时跑呢,假如内存只有32个g,每天泄露一点,那机器不就越来越卡了?,最后只会卡死,卡死了就重启,又卡死,再重启。这种问题就会对我们的机器的使用造成很大困扰。所以内存泄漏其实是一个比较严重的问题,所以我们一定要记得free().
尾声
看到这里,相信你对动态内存使用的一些雷区有了更深的了解,也相信你已经学会了避免这些问题的方法。
如果你感觉这期博客对你帮助的话,别忘了转发,收藏,点赞,关注,一波四连再走哦!
【动态内存】C语言动态内存使用常见错误及其避免方法(初学者避雷)的更多相关文章
- 深入理解C语言 - 指针使用的常见错误
在C语言中,指针的重要性不言而喻,但在很多时候指针又被认为是一把双刃剑.一方面,指针是构建数据结构和操作内存的精确而高效的工具.另一方面,它们又很容易误用,从而产生不可预知的软件bug.下面总结一下指 ...
- R语言编程中的常见错误
R语言编程中的常见错误有一些错误是R的初学者和经验丰富的R程序员都可能常犯的.如果程序出错了,请检查以下几方面. 使用了错误的大小写.help().Help()和HELP()是三个不同的函数(只有第 ...
- 微信jssdk常见错误及解决方法
调用config 接口的时候传入参数 debug: true 可以开启debug模式,页面会alert出错误信息.以下为常见错误及解决方法: invalid url domain当前页面所在域名与使用 ...
- WCF项目中出现常见错误的解决方法:基础连接已经关闭: 连接被意外关闭
在我们开发WCF项目的时候,常常会碰到一些莫名其妙的错误,有时候如果根据它的错误提示信息,一般很难定位到具体的问题所在,而由于WCF服务的特殊性,调试起来也不是那么方便,因此往往会花费不少时间来进行跟 ...
- Servlet常见错误及解决方法
常见错误及解决方法 1. 404产生的原因为Web服务器(容器)根据请求地址找不到对应资源,以下情况都会出现404的错误提示: 输入的地址有误(应用名大小写不正确,名称拼写不正确) 在web.xml文 ...
- IIS7常见错误及解决方法
IIS7常见错误及解决方法 问题一:HTTP 错误 500.19 - Internal Server Error 无法访问请求的页面,因为该页的相关配置数据无效. 详细错误信息模块 IIS We ...
- centos linux 系统日常管理4 scp,rsync,md5sum,sha1sum,strace ,find Rsync 常见错误及解决方法 第十七节课
centos linux 系统日常管理4 scp,rsync,md5sum,sha1sum,strace ,find Rsync 常见错误及解决方法 第十七节课 rsync可以增量同步,scp不行 ...
- python循环删除列表元素常见错误与正确方法
python循环删除列表元素 觉得有用的话,欢迎一起讨论相互学习~Follow Me 常见错误 常见错误一:使用固定长度循环删除列表元素 # 使用固定长度循环pop方法删除列表元素 num_list_ ...
- cmd常见错误及解决方法
[英文] Bad command or file name [译文] 错误的命令或文件名 错误原因和解决: 这大概是大家最常见到的错误提示了,它的意思是输入的命令无效.当输入的命令既不是DOS内部命令 ...
- jmeter常见错误及解决方法
jmeter常见错误: 错误一: Response code: Non HTTP response code: java.net.SocketTimeoutException Response m ...
随机推荐
- Educational Codeforces Round 109 (Rated for Div. 2) 个人补题记录(A~D,AB思维,C模拟构造,D题DP)
补题链接:Here 1525A. Potion-making (思维 [题意描述] 作为一个魔法师,现在我想配置一杯药物浓度为 \(k\%\) 的药水, 每次操作能进行添加: 一升水 一升药物精华 作 ...
- 图解 Promise 实现原理(三)—— Promise 原型方法实现
本文首发于 vivo互联网技术 微信公众号 链接: https://mp.weixin.qq.com/s/u8wuBwLpczkWCHx9TDt4Nw作者:Morrain Promise 是异步编程 ...
- Kafka的Rebalance机制可能造成的影响及解决方案
一.kafka的rebalance机制在Kafka中,当有新消费者加入或者订阅的Topic数发生变化时,会触发Rebalance(再均衡:在同一个消费者组当中,分区的所有权从一个消费者转移到另外一个消 ...
- 二、redis主从环境搭建
系列导航 一.redis单例安装(linux) 二.redis主从环境搭建 三.redis集群搭建 四.redis增加密码验证 五.java操作redis 环境:centos7需要的安装包: redi ...
- C语言哈希表uthash的使用方法详解(附下载链接)
uthash简介 由于C语言本身不存在哈希,但是当需要使用哈希表的时候自己构建哈希会异常复杂.因此,我们可以调用开源的第三方头文件,这只是一个头文件:uthash.h.我们需要做的就是将头文件复制 ...
- 从输入URL后浏览器的渲染逻辑
从输入URL到浏览器渲染页面需要经过很多过程,本文简单说明下各个环节的内容 主要渲染节点如下: 一.浏览器进程说明 出于安全考虑,打开一个浏览器的Tab页签,会生成1个浏览器主进程.1个网络进程.1个 ...
- P1004-DP【绿】
这道题很有趣,暴搜的时间复杂度太过于凶残O(K*(2^n)^2)(K的意思是大常数),不过作为提高组T4,这道题数据范围太小了,感觉哪怕是离谱的暴搜也能过. 再加上一时半会没想好多项式时间复杂度的正解 ...
- andriod sdk安装与使用
一.进入以下网站下载 https://www.androiddevtools.cn/ 选择sdk工具-sdktools,这个工具比较好,可以通过SDK Manager下载到各种想要的包 有zip与ex ...
- 安装MicroStation软件、Terrasolid插件的方法
本文介绍在Win10电脑中,安装MicroStation软件与Terrasolid插件合集的详细方法. 首先,我们需要有MicroStation软件与Terrasolid插件合集的安装包:这些 ...
- 4. Oracle数据库提示ERROR: ORA-12560: TNS: 协议适配器错误
问题如下 造成ORA-12560: TNS: 协议适配器错误的问题的原因有两个: 有关服务没有启动 windows平台个一如下操作:开始-程序-管理工具-服务,打开服务面板,启动TNSlistener ...