




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第第页如何正确使用动态内存?一.
常见错误与预防
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. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2019-2025年一级注册建筑师之设计前期与场地设计能力测试试卷B卷附答案
- 2025年建筑工程合同风险评估与控制策略研究
- 西宁eps线条施工方案
- 成就分享的年度绩效评估计划
- 高科技行业年度工作目标设定计划
- emba培训课程合同样本
- 教师课堂评价体系计划
- epc项目监理合同样本
- 农机撒粪机租赁合同样本
- 2025工程咨询合同 标准版 模板
- 中小学生航天知识竞赛题库及答案(215题)
- 浙江省杭州市2024年中考英语真题(含答案)
- 2024年高等教育法学类自考-00249国际私法考试近5年真题附答案
- 外研版(2021)中职英语基础模块1 Unit 8 Enjoy the Festivals Listening&Speaking 教案
- 2024年汽车驾驶员(技师)职业鉴定理论考试题库(含答案)
- 2024年青岛市中考数学试卷(含答案解析)+2023年试卷及答案详解
- GB/T 15568-2024通用型片状模塑料(SMC)
- 冷库建设日常运营与维护保养方案
- 【真题】2024年镇江市中考道德与法治试卷(含答案解析)
- 生猪屠宰兽医卫生检验人员理论考试题库及答案
- 监理见证取样工作计划
评论
0/150
提交评论