如何正确使用动态内存_第1页
如何正确使用动态内存_第2页
如何正确使用动态内存_第3页
如何正确使用动态内存_第4页
如何正确使用动态内存_第5页
已阅读5页,还剩1页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第第页如何正确使用动态内存?一.

常见错误与预防

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. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论