版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第第页如何正确使用动态内存?一.
常见错误与预防
1.
分配后忘记释放内存
void
func(void){
p
=
malloc(len);
do_something(p);
return;
/*错误!退出程序时没有释放内存*/}
预防:
编写代码时malloc()和free()保证成对出现,避免忘记资源回收。
int
func(void){
p
=
malloc(len);
if
(condi(ti)on)
return
-1;
/*错误!退出程序时没有释放内存*/
free(p);
return
0;}
预防:
一旦使用动态内存分配,请仔细检查程序的退出分支是否已经释放该动态内存。
2.
释放内存调用错误指针
void
func(void){
p
=
malloc(len);
val
=
*p++;
/*错误!动态内存句柄不可移动*/
free(p);}
预防:
千万不要修改动态内存句柄!可以另外赋值给其他指针变量,再对该动态内存进行访问操作。
3.
分配内存不够导致溢出
void
func(void){
len
=
strlen(str);
p
=
malloc(len);
strcpy(p,
str);
/*错误!str的’�’写到动态内存外*/}
预防:
分配内存前仔细思考长度是否足够,千万注意字符串拷贝占用内存比字符串长度大1。
二.
自动查错机制
尽管在开发过程中坚守原则和谨慎(编程)甚至严格测试,然而内存泄露的错误还是难以杜绝,如何让系统自动查出内存泄露的错误呢?
一种比较好的方法是建立日志块,即每次分配内存时记录该内存块的指针和大小,释放时再去除该日志块,如果有内存泄露就会有对应的日志块记录这些内存没有释放,这样就可以提醒(程序员)进行查错。
有了上述日志块操作函数,再来实现动态内存分配与释放函数就很容易了。只有当处于DEBUG版本和打开内存调试DMEM_DBG时才进行日志登录,否则MallocExt()和FreeExt()函数与malloc()和free()是等价的,这样保证了系统处于发布版本时的性能。
(代码已经过严格测试,但这不是盈利的商业代码,即没有版权。但如果因代码错误带来的任何损失具有免责权利)
代码部分:
首先定义日志块结构体:
/*
Log
of
dynamic
mem(or)y
usage
*/typedef
struct
_dmem_log{
struct
_dmem_log
*p_stNext;
/*
Point
to
next
log
*/
const
void
*p_vDMem;
/*
Point
to
alloca(te)d
memory
by
this
pointer
*/
INT32S
iSize;
/*
Size
of
the
allocated
memory
*/}
DMEM_LOG;
然后为该结构体开辟内存:
stat(ic)
DMEM_LOG
*s_ps(tF)reeLog;
/*
Point
to
free
log
pool
by
this
pointer
*/static
INT8U
s_byNumUsedLog;static
DMEM_LOG
*s_pstHe(ad)Log;
/*
Point
to
used
log
chain
by
this
pointer
*//*
Pool
of
dynamic
memory
log
*/#define
NUM_DMEM_LOG
20static
DMEM_LOG
s_astDMemLog[NUM_DMEM_LOG];
下面是内存日志块的操作函数:初始化、插入日志和移除日志:
/**********************************************************
*
Initialize
DMem
Log*
Description
:
Initialize
log
of
dynamic
memory*
Arguments
:
void*
Returns
:
void*
Notes
:**********************************************************/static
void
InitDMemLog(void){
INT16S
nCnt;
/*
Initialize
pool
of
log
*/
for
(nCnt
=
0;
nCnt
p_stNext;
OS_EXIT_CRITICAL();
/*
Don't
need
to
protect
this
log
that
is
free
one
currently
*/
p_stLog->p_vDMem
=
p_vAddr;
p_stLog->iSize
=
iSize;
/*
Put
this
log
into
used
chain
*/
OS_ENTER_CRITICAL();
/*
Avoid
race
condition
*/
p_stLog->p_stNext
=
s_pstHeadLog;
s_pstHeadLog
=
p_stLog;
++s_byNumUsedLog;
OS_EXIT_CRITICAL();
return;}/**********************************************************
*
Unlog
DMem*
Description
:
Remove
an
allocated
memory
from
log
pool*
Arguments
:
const
void
*p_vAddr
point
to
address
of
this
allocated
memory
by
this
pointer*
Returns
:
void*
Notes
:**********************************************************/static
void
UnlogDMem(const
void
*p_vAddr){
ASSERT(p_vAddr);
DMEM_LOG
*p_stLog,
*p_stPrev;
#if
OS_CRITICAL_METHOD
==
3
OS_CPU_SR
cpu_sr;
#endif
/*
Search
the
log
*/
OS_ENTER_CRITICAL();
/*Avoid
race
condition
*/
p_stLog
=
p_stPrev
=
s_pstHeadLog;
while
(p_stLog)
{
if
(p_vAddr
==
p_stLog->p_vDMem)
{
break;
/*
Have
found
*/
}
p_stPrev
=
p_stLog;
p_stLog
=
p_stLog->p_stNext;
/*
Move
to
next
one
*/
}
if
(!p_stLog)
{
OS_EXIT_CRITICAL();
PRINTF("Search
Log
failed.");
return;
}
/*
Remove
from
used
pool
*/
if
(p_stLog
==
s_pstHeadLog)
{
s_pstHeadLog
=
s_pstHeadLog->p_stNext;
}
else
{
p_stPrev->p_stNext
=
p_stLog->p_stNext;
}
--s_byNumUsedLog;
OS_EXIT_CRITICAL();
/*
Don't
need
to
protect
this
log
that
is
free
one
currently
*/
p_stLog->p_vDMem
=
NULL;
p_stLog->iSize
=
0;
/*
Add
into
free
pool
*/
OS_ENTER_CRITICAL();
/*
Avoid
race
condition
*/
p_stLog->p_stNext
=
s_pstFreeLog;
s_pstFreeLog
=
p_stLog;
OS_EXIT_CRITICAL();
return;}
带日志记录功能的内存分配MallocExt()和内存释放FreeExt()函数:
/*********************************************************
*
Malloc
Extension*
Description
:
Malloc
a
block
of
memory
and
log
it
if
need*
Arguments
:
INT32S
iSize
size
of
desired
allocate
memory*
Returns:
void
*NULL=
failed,
otherwise=pointer
of
allocated
memory*
Notes
:**********************************************************/void
*MallocExt(INT32S
iSize){
ASSERT(iSize
>
0);
void
*p_vAddr;
p_vAddr
=
malloc(iSize);
if
(!p_vAddr)
{
PRINTF("malloc
failed
at
%s
line
%d.",
__FILE__,
__LINE__);
}
else
{
#if
(DMEM_DBG
/*
Fill
gargage
for
debug
*/
LogDMem(p_vAddr,
iSize);
/*
Log
memory
for
debug
*/
#endif
}
return
p_vAddr;
}/***********************************************************
Free
Extension*
Description
:
Free
a
block
of
memory
and
unlog
it
if
need*
Arguments
:
void
*
p_vMem
point
to
the
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 人力资源工作心得体会15篇
- 《历史文化名城主题公园景观设计中的地域文化元素整合与创新》教学研究课题报告
- 高中语文课堂传统文化故事教学与文学素养的拓展教学研究课题报告
- 医药行业软件系统测试流程详解
- 《铸造行业清洁生产技术改造对区域环境质量的改善效果评估》教学研究课题报告
- 微软技术部门面试题集及解答
- 社区公共设施在初中生课余生活娱乐方式选择中的影响教学研究课题报告
- 2025安徽润含林业发展有限公司招聘劳务派遣人员4人笔试参考题库附带答案详解(3卷)
- 青田县2024年浙江丽水青田县引进“政聘企用”高层次和急需紧缺人才5人事业编制笔试历年参考题库典型考点附带答案详解(3卷合一)
- 高中生物实验教学与多媒体技术整合的课题报告教学研究课题报告
- 小学美术四年级上册 3. 周末日记 公开课比赛一等奖
- 酒店行业的信息安全培训方法
- 塑料制品行业财务工作年度绩效报告
- 皮肤科护理中的振动按摩在皮肤病管理中的应用
- 20以内进位加法100题(精心整理6套-可打印A4)
- 肠内营养考评标准终
- 2023届高考专题复习:小说专题训练群体形象与个体形象(含答案)
- 项目全周期现金流管理培训
- 生物化学实验智慧树知到答案章节测试2023年浙江大学
- 等腰三角形复习课教案
- GB/T 39741.1-2021滑动轴承公差第1部分:配合
评论
0/150
提交评论