首页
论坛
电子技术基础
模拟技术
可编程器件
嵌入式系统与MCU
工程师职场
最新帖子
问答
版主申请
每月抽奖
商城免费换礼
社区有奖活动
博客
下载
评测
视频
文库
芯语
资源
2024国际航空电子大会
2024国际 AIoT 生态发展大会
3D IC 设计和Chiplet资料下载
车载总线测试和解码方案
新能源汽车三电测试技术中心
在线研讨会
EE直播间
小测验
白皮书
行业及技术活动
杂志免费订阅
免费在线工具
厂商资源中心
论坛
博文
电子工程专辑
电子技术设计
国际电子商情
资料
白皮书
研讨会
芯语
文库
登录|注册
登录
最新发表
推荐阅读
明星博主
原创博文
年度排行
博文排行
博文评论
FPGA/CPLD
MCU/ 嵌入式
模拟
电源/新能源
测试测量
通信
智能手机
处理器与DSP
PCB
汽车电子
消费电子
智能硬件
物联网
软件与OS
采购与分销
供应链管理
工程师职场
EDA/ IP/ 设计与制造
无人机
机器人/ AI
医疗电子
工业电子
管理
写博文
用户1615276
修改
文章:
67
阅读:
154507
评论:
36
赞:
520
好友
私信
个人主页
文章
67
原创
0
阅读
154507
评论
36
赞
520
原创
C语言指针和内存泄漏问题
2008-10-26 18:50
2125
7
7
分类:
MCU/ 嵌入式
在使用 C 语言时,您是否对花时间调试指针和内存泄漏问题感到厌倦?如果是这样,那么本文就适合您。您将了解可能导致内存破坏的指针操作类型,您还将研究一些场景,了解要在使用动态内存分配时考虑什么问题。
引言
对
于任何使用 C 语言的人,如果问他们 C
语言的最大烦恼是什么,其中许多人可能会回答说是指针和内存泄漏。这些的确是消耗了开发人员大多数调试时间的事项。指针和内存泄漏对某些开发人员来说似乎
令人畏惧,但是一旦您了解了指针及其关联内存操作的基础,它们就是您在 C 语言中拥有的最强大工具。
本文将与您分享开发人员在开始使用指针来编程前应该知道的秘密。本文内容包括:
导致内存破坏的指针操作类型
在使用动态内存分配时必须考虑的检查点
导致内存泄漏的场景
如果您预先知道什么地方可能出错,那么您就能够小心避免陷阱,并消除大多数与指针和内存相关的问题。
什么地方可能出错?
有几种问题场景可能会出现,从而可能在完成生成后导致问题。在处理指针时,您可以使用本文中的信息来避免许多问题。
未初始化的内存
在本例中,p 已被分配了 10 个字节。这 10 个字节可能包含垃圾数据,如图 1 所示。
char *p = malloc ( 10 );
图 1. 垃圾数据
如果在对这个 p 赋值前,某个代码段尝试访问它,则可能会获得垃圾值,您的程序可能具有不可预测的行为。p 可能具有您的程序从未曾预料到的值。
良好的实践是始终结合使用 memset 和 malloc,或者使用 calloc。
char *p = malloc (10);
memset(p,’\0’,10);
现在,即使同一个代码段尝试在对 p 赋值前访问它,该代码段也能正确处理 Null 值(在理想情况下应具有的值),然后将具有正确的行为。
内存覆盖
由于 p 已被分配了 10 个字节,如果某个代码片段尝试向 p 写入一个 11 字节的值,则该操作将在不告诉您的情况下自动从其他某个位置“吃掉”一个字节。让我们假设指针 q 表示该内存。
图 2. 原始 q 内容
图 3. 覆盖后的 q 内容
结果,指针 q 将具有从未预料到的内容。即使您的模块编码得足够好,也可能由于某个共存模块执行某些内存操作而具有不正确的行为。下面的示例代码片段也可以说明这种场景。
char *name = (char *) malloc(11);
// Assign some to name
memcpy ( p,name,11); // Problem begins here
在本例中,memcpy 操作尝试将 11 个字节写到 p,而后者仅被分配了 10 个字节。
作为良好的实践,每当向指针写入值时,都要确保对可用字节数和所写入的字节数进行交叉核对。一般情况下,memcpy 函数将是用于此目的的检查点。
内存读取越界
内存读取越界 (overread) 是指所读取的字节数多于它们应有的字节数。这个问题并不太严重,在此就不再详述了。下面的代码提供了一个示例。
char *ptr = (char *)malloc(10);
char name[20] ;
memcpy ( name,ptr,20); // Problem begins here
在本例中,memcpy 操作尝试从 ptr 读取 20 个字节,但是后者仅被分配了 10 个字节。这还会导致不希望的输出。
内存泄漏
内存泄漏可能真正令人讨厌。下面的列表描述了一些导致内存泄漏的场景。
重新赋值
我将使用一个示例来说明重新赋值问题。
char *memoryArea = malloc(10);
char *newArea = malloc(10);
这向如下面的图 4 所示的内存位置赋值。
图 4. 内存位置
memoryArea 和 newArea 分别被分配了 10 个字节,它们各自的内容如图 4 所示。如果某人执行如下所示的语句(指针重新赋值)……
memoryArea = newArea;
则它肯定会在该模块开发的后续阶段给您带来麻烦。
在上面的代码语句中,开发人员将 memoryArea 指针赋值给 newArea 指针。结果,memoryArea 以前所指向的内存位置变成了孤立的,如下面的图 5 所示。它无法释放,因为没有指向该位置的引用。这会导致 10 个字节的内存泄漏。
图 5. 内存泄漏
在对指针赋值前,请确保内存位置不会变为孤立的。
首先释放父块
假设有一个指针 memoryArea,它指向一个 10 字节的内存位置。该内存位置的第三个字节又指向某个动态分配的 10 字节的内存位置,如图 6 所示。
图 6. 动态分配的内存
free(memoryArea)
如果通过调用 free 来释放了 memoryArea,则 newArea 指针也会因此而变得无效。newArea 以前所指向的内存位置无法释放,因为已经没有指向该位置的指针。换句话说,newArea 所指向的内存位置变为了孤立的,从而导致了内存泄漏。
每当释放结构化的元素,而该元素又包含指向动态分配的内存位置的指针时,应首先遍历子内存位置(在此例中为 newArea),并从那里开始释放,然后再遍历回父节点。
这里的正确实现应该为:
free( memoryArea->newArea);
free(memoryArea);
返回值的不正确处理
有时,某些函数会返回对动态分配的内存的引用。跟踪该内存位置并正确地处理它就成为了 calling 函数的职责。
char *func ( )
{
return malloc(20); // make sure to memset this location to ‘\0’…
}
void callingFunc ( )
{
func ( ); // Problem lies here
}
在上面的示例中,callingFunc() 函数中对 func() 函数的调用未处理该内存位置的返回地址。结果,func() 函数所分配的 20 个字节的块就丢失了,并导致了内存泄漏。
归还您所获得的
在开发组件时,可能存在大量的动态内存分配。您可能会忘了跟踪所有指针(指向这些内存位置),并且某些内存段没有释放,还保持分配给该程序。
始终要跟踪所有内存分配,并在任何适当的时候释放它们。事实上,可以开发某种机制来跟踪这些分配,比如在链表节点本身中保留一个计数器(但您还必须考虑该机制的额外开销)。
访问空指针
访问空指针是非常危险的,因为它可能使您的程序崩溃。始终要确保您不是 在访问空指针。
总结
本文讨论了几种在使用动态内存分配时可以避免的陷阱。要避免内存相关的问题,良好的实践是:
始终结合使用 memset 和 malloc,或始终使用 calloc。
每当向指针写入值时,都要确保对可用字节数和所写入的字节数进行交叉核对。
在对指针赋值前,要确保没有内存位置会变为孤立的。
每当释放结构化的元素(而该元素又包含指向动态分配的内存位置的指针)时,都应首先遍历子内存位置并从那里开始释放,然后再遍历回父节点。
始终正确处理返回动态分配的内存引用的函数返回值。
每个 malloc 都要有一个对应的 free。
确保您不是在访问空指针。
写原创有奖励!2024面包板原创奖励正在进行中
点赞(
7
)
收藏
分享到:
上一篇:
编程修养(三)
下一篇:
C语言的宏定义
PARTNER CONTENT
换一换>
更多>
新蓝牙6.0协议扩展应用范围
Silicon Labs(芯科科技)蓝牙产品经理Parker Dorris
2024-12-16
概伦电子:以开放心态共绘EDA产业新蓝图
概伦电子
2024-12-30
SK海力士开发出适用于AI数据中心的高容量固态硬盘‘PS1012 U.2’
SK海力士
2024-12-18
SK海力士将在CES2025亮相‘全方位面向AI的存储器供应商’的新蓝图
SK海力士
2025-01-03
文章评论
(
0
条评论)
登录
后参与讨论
您需要登录后才可以评论
登录
|
立即注册
发布
用户1615276
修改
文章:
67
阅读:
154507
评论:
36
赞:
520
好友
私信
个人主页
文章
67
原创
0
阅读
154507
评论
36
赞
520
最新评论
更多
写的好,好产品,海信了不起
开发工匠 ...
评论博文
2025-1-11
海信发布全球首台116英寸RGB-Mini LED电视 ...
物也有命
自做自受 ...
评论博文
2025-1-9
富士通环保行为准则之切身感受 ...
行情不坏,手机火,写的好
开发工匠 ...
评论博文
2025-1-9
2024年全球智能手机面板出货量突破22亿片, ...
最新
博文
简单又实用的教程:RTC时钟使用指南~ ...
一篇文章丨教会你从外观上辨别PCB板层 ...
艾体宝案例丨Snyk 如何借助 CircleCI ...
资料下载
本周热帖
Processing-processing3.5.4
ESP32TFT常用字体库.zip
自动增益控制放大器设计与实现 ...
无线传能充电器设计与实现论文 ...
基于单片机自动电阻测试仪设计论文 ...
《极简图解 半导体技术基本原理》+半 ...
【工程师故事】+2024年:资深嵌入式工 ...
如何快速检测稳压管的稳压值 ...
浪拓电子小课堂:TVS与TSS的工作原理 ...
AD19使用的两个问题
最新资讯
芯语最新
Altera升起象征独立的公司旗帜,正式 ...
用一种简单的方法进行三进制增益切换 ...
苹果廉价版iPhone将在1月中量产,富士 ...
升旗独立!Altera正式脱离英特尔 ...
中国市场下滑0.1%,美洲地区半导体销 ...
高效国产红外温度传感器,为充电桩行 ...
红外温度传感器在电动汽车动力系统的 ...
研发压电MEMS药液微泵,原位芯片完成 ...
思特威全新推出物联网系列3MP高性能图 ...
亮源激光发布5km激光测距模组,引领全 ...
EE直播间
更多
第三代功率半导体器件测试解决方案
直播时间: 03月06日 10:00
在线研讨会
更多
重塑机器人未来:揭秘创新芯片解决方案的颠覆力量
多路有光·精准不凡——KSW-SGM01模拟信号源发布会
迈来芯Triaxis® 3D磁传感器:汽车安全应用的优选方案
适用于安全连接的新一代PIC32CK SG/GC系列单片机
热门
推荐
【应用手册】TI 全新MCU及C29内核的能源设施应用方案
【应用手册】TI 全新MCU及C29内核的电动汽车应用方案
【TI资料】基于新型C29内核的MCU技术资料
如何提升高压系统的实时性能?
我要评论
0
7
分享到微信
分享到微博
分享到QQ
点击右上角,分享到朋友圈
我知道啦
请使用浏览器分享功能
我知道啦
关闭
站长推荐
/3
工程师写总结,送示波器、稳压电源、螺丝刀!
分享你的:职业生涯中故事、2024年年终总结、工作中的小故事,丰富多样的礼品等你哦!
面包板社区有奖活动汇总楼
1. DIY赢大奖!2. 写原创,有奖励!3.参与话题,奖励E币!4. 免费申领:开发板试用、书籍试读...
电子工程师DIY来分享,赢大疆无人机、小米手机、NAS存储、万用表 ...
展示您的 DIY 电子设计作品,社区将有丰富奖励送给您!
首页
论坛
电子技术基础
模拟技术
可编程器件
嵌入式系统与MCU
工程师职场
最新帖子
问答
版主申请
每月抽奖
商城免费换礼
社区有奖活动
博客
下载
评测
视频
文库
芯语
资源
2024国际航空电子大会
2024国际 AIoT 生态发展大会
3D IC 设计和Chiplet资料下载
车载总线测试和解码方案
新能源汽车三电测试技术中心
在线研讨会
EE直播间
小测验
白皮书
行业及技术活动
杂志免费订阅
免费在线工具
厂商资源中心
帖子
博文
返回顶部
×
文章评论(0条评论)
登录后参与讨论