搜索
查看
编辑修改
首页
UNITY
NODEJS
PYTHON
AI
GIT
PHP
GO
CEF3
JAVA
HTML
CSS
搜索
不正经
这个屌丝很懒,什么也没留下!
关注作者
热门标签
jquery
HTML
CSS
PHP
ASP
PYTHON
GO
AI
C
C++
C#
PHOTOSHOP
UNITY
iOS
android
vue
xml
爬虫
SEO
LINUX
WINDOWS
JAVA
MFC
CEF3
CAD
NODEJS
GIT
Pyppeteer
article
热门文章
1
大数据设计为何要分层,行业常规设计会有几层数据
2
ROC,AUC,Precision,Recall,F1的介绍与计算_auc和recall有什么大小关系吗
3
前端常用插件_前端渲染插件有哪些
4
情感分析的工具:常见的开源库和框架
5
【学习笔记--短文--对比学习1】:深度学习中的正、负采样 & 正、负样例 & 对比学习初涉_对比学习正样本
6
JS高级面试题汇总
7
Oracle grouping sets、rollup、cube 扩展函数详解_oracle cube函数
8
linux服务器视频转换,将动画gif转换为linux服务器上的视频,同时保留帧速率
9
今日arXiv精选 | ICCV 2021/CIKM 2021/ACM MM 2021
10
Kafka快速入门(最新版3.6.0)_kafka3.6
当前位置:
article
> 正文
嵌入式软件开发------指针和内存释放的问题分析_内存池如何释放资源 嵌入式指针
作者:不正经 | 2024-04-07 21:59:22
赞
踩
内存池如何释放资源 嵌入式指针
指针和内存的问题关于指针分配是否要delete的问题:
1.请大家在使用指针变量时遵守以下几点,可以让你们在编程时
少许多的麻烦,以下假设p为某个类型的指针变量。
(1)定义指针:
(a)定义指针变量时赋初值为type* p=NULL;
若是指针数组,刚用循环语句集体赋初值为NULL,
或调用api函数ZeroMemory(指针数组开始地址,0,数组大小(按字节算));
(2)使用指针:
(a)确定是否已经指向某个地址。
请用if(p!=NULL)
正常语句;
else
TRACE("p points to NULL");
使用TRACE(..)函数对调试非常有用
(b)要确定指针变量所指向的变量的类型。
如在使用语句p++,p--时,更要如此,有时还要注意到
类型的强制转换,以及类型强制转换带来的后果。
同时,最好先用pOld=p保存起来
(c)当动态申请内存时,如p=new 某个类型;
在这种用途时,一般来说p之前不会指向某个普通变量(视具体程序而不同),
所以可采用
if(p==NULL)
{
p=new 某个类型;
if ( !p ) { … } //在new以后立刻检查是否得到有效的空间
}
else
出错处理;
若是p在new之前已经不等于0,则很可能是之前已经为p申请某些动态内存,
需要及时释放。
对应于这种情况,因此在释放p所指向的内存时,
建议使用
if(p!=NULL)
{
delete p; // (或delete []p;看情况了)
p=NULL; // 请注意最好加上这一句。 delete操作只是释放p所指向的内存,
但是并不将
// p赋值为NULL。
}
(d)请最好不要将两个指针变量指向同一块动态内存,
因为其中一个释放了动态内存以后,虽然另一个指针
所指向的内存地址不等于NULL,但是因为内存已被释放,
所以若用这个指针时,则会出错。
如果需要将两个指针指向同一个动态内存的话,
则在编程时要特别小心。
(3)释放指针所指向的动态内存时:
(a)上面已经讲到两种情况
(b)最好将类的成员变量中的指针全部赋值为NULL(有时则可以为NULL,
或肯定不能赋为NULL,如在成员变量是static类型时,视程序而定)。
2.在类里面用到动态分配内存的指针,下面是规范的4部曲
(1) 构造函数中 m_pData=NULL; (2)重复更新和分配 if (m_pData!=NULL)
delete []m_pData;// or delete m_pData; m_pData=new ..... (3).所有使用指针的
地方 if(m_pData!=NULL) { } else
TRACE("p points to NULL"); (4).析构函数 if(m_pData) delete []m_pData;
// or delete m_pData;
<说明一点>:类里面用到指针成员变量是很容易出错的一个地方;
我们把一个指针作为成员变量,在某个或者某些成员函数中,要多次给他分配内存,当然,
我们再分配之前必须保证它原先没有指向任何内存(否则就内存泄漏了)
如果判断呢,我想大部分人会这么写:
if (m_pData!=NULL) delete []m_pData;// or delete m_pData; m_pData=new .
....
就是用m_pdata是否为NULL来判断指针是否已经有内存,
那么如果我在别的地方将这块内存delete后没有把指针置为NULL,那么碰到
这样的判断语句会发生什么样的情况,想必大家都看到了。
3.内存分配和释放的分工问题。 我觉得应该明确分配和释放的角色,一个指针只有唯一
一个对象分配,也有唯一一个对 象释放。 绝对应该避免多头分配释放问题。 COM中的内存
分配原则就是很好的例子 COM接口的参数,有三种方向类型[in],[out],[in,out] [in]指针
的内存,是在调用者分配空间调用者释放 [out]指针的内存,是被调用者分配,调用者释放
,且调用者不需要事先初始化 [in,out]指针内存,调用者必须初始化,被调用者可以根据
需要是否重新分配内存 最后由调用者进行清理。 不管哪种形式,一个地址的分配和释放总
是唯一的。 所以,在 FatMouse刚才的那个例子中 p到底是由子类维护还是父类维护呢?
事实上,由于子类的析构函数自动调用父类的析勾函数 子类不需要对父类的指针进行释放
。
4.动态分配内存后不释放是肯定会有内存泄漏的
有一种说法是程序退出的时候编译器是会做内存回收的,我看了一下代码,发现退出main的
时候是会做一些清理工作,主要是把栈清除一下;
运行的时候的调用栈是这样:
main()
maincrtstrartup()
kernel32
其中:
mainCRTStartup:
。。。。。。
00421F30 mov edx,dword ptr [__environ (0047c3dc)]
00421F36 push edx
00421F37 mov eax,[___argv (0047c3d4)]
00421F3C push eax
00421F3D mov ecx,dword ptr [___argc (0047c3d0)]
00421F43 push ecx
00421F44 call @ILT+550(_main) (0040122b)
00421F49 add esp,0Ch
00421F4C mov dword ptr [mainret],eax
00421F4F mov edx,dword ptr [mainret]
00421F52 push edx
00421F53 call exit (00426040)
。。。。。
先是向栈压入edx,随后压入命令行参数,在返回之前pop出命令行参数,edx,返回之后,
把返回值保留在edx中,随后再次压入栈内,调用exit()
并没有垃圾内存的回收(即delete那块new出来的内存/现在已经没有指针变量可以标示
它了)
之所以你没有delete而在退出程序后觉得好像没有内存泄漏我想是操作系统为你做了垃圾
collector的
工作,一个操作系统要是连这个都做不到 那他也太懒了
5.关于内存释放的时机
有一种习惯说是在退出程序的时候释放所有已经分配的内存,同时指针置为null,我认为到了
退出时再释放内存已经太晚了,而且没有任何意义(如上所见反正系统会帮你释放得),释放
内存应该在不再使用时就立刻释放。
常见的内存分配和使用错误
1) 内存的申请和分配并没有成功,但程序员却使用了它。一些新手经常会犯这种错误,他们并不会留意到内存没有分配成功。判断指针的值是否为NULL可以有效地避免这种错误。
2) 内存的分配已经成功,但是却没有进行初始化就直接使用它了。首先是观念上的问题,很多人都没有在使用指针前要初始化这样的习惯,然而这个习惯却是很重要的,希望大家一定要强迫自己养成。第二就是主观地认为自己申请的内存的缺省值为0,这样想是没有什么道理的,内存分配后的值是不确定的。
3) 上面的两种工作都已经做好了(已经成功申请并初始化完成),但是操作时却越界了。
4) 申请了内存,使用完了却忘记了释放,导致内存泄露。这样的错误可以形容为一个恶性的肿瘤,它不会马上要你的命,但是它会慢慢地吞噬你的系统资源,直到你的程序彻底完蛋。
5) 你很小心地释放了内存,但是却又使用了它。由于程序很复杂或者调用顺序出错,这样可能导致出现上面的错误。
指针---一把伟大的双刃剑
我真的非常佩服发明指针的人,他简直太伟大了。能使用如此简洁地方法将复杂的内存结构描述的如此清楚,这本身就是一种伟大的成就。但是,指针之于程序员如同武器之于士兵,用好了可以威力无比,用不好则害人害己。
我先说说指针和数组的区别。数组名对应着一块内存,它的地址、容量在其生命周期中是不可变的,只有数组内容是可变的。指针可随时指向任何类型的内存,它的特点就是“变”。指针远比数组灵活,但也更危险。
数组名是不能直接进行赋值和比较的。如果你向要将数组a赋值给数组b,不能直接用赋值语句b = a ,这样会令编译器产生错误的。必须使用标准的库函数strcpy来进行赋值。相同地,要比较a和b的内容是否相同,不能使用普通的逻辑判断if(b==a),也要应用库函数strcmp来判断。
//数组……
char a[] = “hello”;
char b[100];
strcpy(b, a); // b = a is wrong
if (strcmp(b, a) == 0) //if (b == a) is wrong
cout<<b<<endl;
//指针……
int len = strlen(a);
char *p = (char *)malloc(sizeof(char)*(len+1));
strcpy(p, a);
if (strcmp(p, a) == 0)
cout<<p<<endl;
free(p);
在计算内存容量的时候有一点是必须要指出的,那就是sizeof计算数组是计算它的实际的内存容量,而计算指针时则永远都是4个字节。C++是永远没有办法知道指针所指的内存容量,除非在申请时记住它。
free和delete如何对付指针?
程序员都知道它们是用来释放申请的内存的,但是却很少有人注意到指针本身并没有发生什么变化。各位可以在VC中使用单步跟踪一下,你们会惊奇地发现当指针p被调用了free后它的地址值并没有改变,只是该地址对应的内存中原来有意义的值变成了垃圾,“p”却还是指向的这块内存。记住,一定要第一时间将p的值设为NULL,否则会让别人以为p是一个有意义的指针而误使用它(当别人使用该指针时会判断指针的值是否为NULL,如果不为NULL就会以为它有意义)。
也就是说调用了free(p)之后,p仍然指向那块内存,假若不显示设置为NULL的话,以后就不能使用if (NULL == p)来判断p是否释放
char *p = (char *)malloc(100);
strcpy(p, “hello”);
free(p); // the address of “p” is not changed.
….
if (NULL != p) //it will return TRUE
strcpy(p, “world”); //Wrong!!!
下面提两点,让大家可以防止上面的情况出现:
1) 指针声明后要马上初始化。因为指针出现的缺省值是随机的,所以一定要赋值为NULL,然后再使用。
2) 调用了free和delete后一定要将指针赋值为NULL。原因上面已经提过了,就不再赘述了。
C++父类子类指针函数调用注意事项(虚拟函数与多型Polymorphism)
1,如果以一个基础类指针指向一个衍生类对象,那么经由该指针只能访问基础类定义的函数
2,如果以一个衍生类指针指向一个基础类对象,必须先做强制转型动作(explicit cast),这种做法很危险,也不符合生活习惯,在程序设计上也会给程序员带来困扰。
3,如果基础类和衍生类定义了相同名称的成员函数,那么通过对象指针调用成员函数时,到底调用那个函数要根据指针的原型来确定,而不是根据指针实际指向的对象类型确定。
虚拟函数就是为了对“如果你以一个基础类指针指向一个衍生类对象,那么通过该指针,你只能访问基础类定义的成员函数”这条规则反其道而行之的设计。
如果你预期衍生类由可能重新定义一个成员函数,那么你就把它定义成虚拟函数( virtual )。
polymorphism就是让处理基础类别对象的程序代码能够通透的继续适当地处理衍生类对象。
纯虚拟函数:
virtual void myfunc ( ) =0;
纯虚拟函数不许定义其具体动作,它的存在只是为了在衍生类钟被重新定义。只要是拥有纯虚拟函数的类,就是抽象类,它们是不能够被实例化的。如果一个继承类没有改写父类中的纯虚函数,那么他也是抽象类,也不能被实例化。
抽象类不能被实例化,不过我们可以拥有指向抽象类的指针,以便于操纵各个衍生类。
虚拟函数衍生下去仍然是虚拟函数,而且还可以省略掉关键字“virtual”。
声明:
本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:
https://www.wpsshop.cn/w/不正经/article/detail/380905
推荐阅读
article
Android
Studio
老
版本
下载
方法(2019.11.29)_
android
studio20...
近期学习
Android
开发,找到的资源都是使用
Android
Studio
老
版本
进行教学,与新
版本
在操作上略有不同,学习...
赞
踩
article
【
Flink
基础】
--
Flink
CDC
介绍
...
一、
Flink
CDC
是什么? 2020年
Flink
cdc 首次在
Flink
forward 大会上官宣,由Ja...
赞
踩
article
最新
腾讯
等大厂
c
/
c
++
后
端
linux
开发
常见面试题汇总_
c
++
程序员面试,
linux
部分会问
什么
...
计算机操作系统(Linux):1、命令:netstatt
c
pdumpip
c
s ip
c
rm这四个命令的熟练掌握程度基本上能...
赞
踩
article
商城
优选
小
程序
商城
微信
小
程序
类似“
兴盛
优选
”有人能写吗?_
兴盛
优选
源码...
用Python语言写了一套
商城
小
程序
商城
优选
软件
小
程序
只要有优势货源,盈利操作就很简单,参考“
兴盛
优选
”,通过
商城
的...
赞
踩
article
使用
Dockerfile
文件
部署
项目
,构建
docker
镜像
_
docker
使用
docker
file文...
执行该命令将
项目
jar构建为容器
镜像
。xixishop 已经在
镜像
列表中了。_
docker
使用
docker
file
文件
...
赞
踩
article
Mac环境下
Homebrew
的
安装
指南:步骤解析与常见
问题
解决_
mac
homebrew
安装
网络问...
Mac环境下
Homebrew
的
安装
指南:步骤解析与常见
问题
解决_
mac
homebrew
安装
网络
问题
mac
homeb...
赞
踩
article
解决win下vs+
yolov3
使用Dll载入图片和载入Ma
t
检测
出来效果不一致的问题。
_
s
t
d
:
:
v...
问题描述: 在windows下使用vs2015 + Yolov3的DLL版本时(h
t
t
ps
:
//gi
t
hub.com/A...
赞
踩
article
谈谈
域名
这点
事
...
先说点题外话,最近这几天看到方兴东博士又写了一篇靠臆断的奇文,说苹果和美国政府演了一场双簧。本来想写一篇抨击的,结果发现...
赞
踩
article
Python实战项目——用户
消费
行为
数据
分析
(三)_
数据挖掘
消费者
行为
分析
...
大多数用户最后一次购买时间集中在前3个月,说明缺少忠诚用户。随着时间的推移,最后一次购买商品的用户量呈现上升趋势,猜测:...
赞
踩
article
RabbitMQ反
序列化
失败:Failed to
convert
message_org.sprin...
把这个对象放到公共模块,然后生产者和消费者服务引入这个公共模块,生产者和消费者发送和消费时共用一个对象。这样完全保证了两...
赞
踩
article
RabbitMQ
3.13.x之七_
RabbitMQ
消息
队列
模型...
RabbitMQ
3.x之七_
RabbitMQ
消息
队列
模型
RabbitMQ
3.13.x之七_
RabbitMQ
消息
队列
模型 ...
赞
踩
article
计算机
面试
题整理-后台开发
、
软件开发
面试
宝典八股文_
程序员
面试
宝典
csdn
...
网络七层模型和tcp/ip模型 TCP三次握手,四次挥手的过程 TCP为什么是三次握手
、
四次挥手 tcp粘包 基于udp...
赞
踩
article
bower
的
使用
_
bower
国内源...
Bower是一个客户端技术
的
软件包管理器,它可用于搜索、安装和卸载如JavaScript、HTML、CSS之类
的
网络资源...
赞
踩
article
华为
OD机试 - 密码解密(
Java
& JS &
Python
&
C
&
C
++)_密码解密
华为
...
华为
OD机试 - 密码解密(
Java
& JS &
Python
&
C
&
C
++),实现:字符串替换操作_密码解密华...
赞
踩
article
力扣
面试
经典
150
题——27.移除
元素
【
C++
】...
答主原思路:从后向前遍历
元素
,当
元素
等于val时,将当前
元素
置为数组最后一个
元素
,数组长度减一,但是一直报错显示溢出,欢...
赞
踩
article
Java
-
Base64Fiend
工具类...
import java.io.ByteArrayInputStream;import java.io.ByteArray...
赞
踩
article
基于
python
的
植物
大战
僵尸
游戏开发_
pycharm
植物
大战
僵尸
...
基于
python
的
植物
大战
僵尸
游戏开发_
pycharm
植物
大战
僵尸
pycharm
植物
大战
僵尸
...
赞
踩
article
flink
1.15消费
kafka
之
checkpoint
一_
flink
kafka
checkpoi...
flink
1.15源码实践_
flink
kafka
checkpoint
flink
kafka
checkpoint
...
赞
踩
article
2023
基于
微信
小
程序
的
童装
服装服饰
在线商城
系统
(SSM+
mysql
)-
JAVA
.VUE(论文+开题...
本
系统
基于
Web服务模式,是一个适用于Internet环境下
的
模型结构。只要用户能连上Internet,便可以在任何时间...
赞
踩
article
OpenJudge
百炼习题解答(
C++
)
--
题4072:
判断
多个点是否
在
同一
直线
_
c++
如何
判断
在
一...
题:总时间限制: 1000ms 内存限制: 65536kB描述有N(1个互不重合的点,并给出它们的坐标(xi,yi),问...
赞
踩
相关标签
Android Studio
老版本
大数据
flink
linux
后台开发
腾讯
c++
商城小程序
微信小程序
商城优选软件程序
购物商城
docker
容器
运维
macos
Yolov3
python
数据分析
数据挖掘
rabbitmq
分布式
面试
计算机网络