Memory Management文档格式.docx

上传人:b****3 文档编号:16798428 上传时间:2022-11-26 格式:DOCX 页数:11 大小:50.16KB
下载 相关 举报
Memory Management文档格式.docx_第1页
第1页 / 共11页
Memory Management文档格式.docx_第2页
第2页 / 共11页
Memory Management文档格式.docx_第3页
第3页 / 共11页
Memory Management文档格式.docx_第4页
第4页 / 共11页
Memory Management文档格式.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

Memory Management文档格式.docx

《Memory Management文档格式.docx》由会员分享,可在线阅读,更多相关《Memory Management文档格式.docx(11页珍藏版)》请在冰豆网上搜索。

Memory Management文档格式.docx

1.6.1.檢查內存泄漏7

1.6.2.檢查內存重復釋放7

1.6.3.檢查內存越界7

1.6.4.避免在棧中分配過大內存8

1.6.5.注意對指針的使用9

1.6.6.多線程模式下的內存問題10

1.6.7.理解幷遵守平臺(如obigo,OP,BREW)的內存使用原則11

1.简介

1.1.文檔使用者

1.2.参考

本文参考了如下的文档,各个参考文档使用[x]来标记。

1.3.缩略词

1.4.问题报告

有任何关于此文档的问题,请报告给allenq@。

内存和指针的使用和管理是c开发大型项目最重要的内容之一。

不少大型项目的失败都是大量的内存和指针使用不当引起。

下面介绍多线程ui情况下内存模型和使用注意事项。

1.5.内存模型

目前嵌入式的线程模型是单进程多线程的模式。

在这种模式下,内存模式如下

内存分为四大类

●代码段,放置所有的代码

●全局数据段放置全局数据和静态数据,所有线程共享全局数据段

●堆,放置动态分配的内存,所有线程共享堆

●栈,放置线程的局部变量,不同线程有不同的栈

intg_var1;

char*g_var3;

func1()

{

staticdoubles_cc=0;

intf1_var1;

char*f1_var2=malloc(10);

func2();

}

func2()

charf2_var2;

f2_var2++;

g_var3=malloc(10);

假定当前有两个task,task1&

task2

task1调用func1并且运行到了func2的g_var3=malloc(10)代码处

task2调用func1并且运行到了func1的char*f1_var2=malloc(10);

函数处

此时,线程模型如下图

1.6.内存管理原则

内存引起的bug,特定如下

1不会马上引起错误,但以后不确定的某种情况下可能发生错误,而且该错误与诱发错误的地方几乎看不出任何联系

2一旦发生错误,都是致命错误,导致系统crash

3debug非常麻烦

所以”内存使用不当”是用c/c++开发大型项目中最重要的bug之一,尤其经验不是非常丰富的工程师,最容易犯这类错误(其实经验比较丰富的工程师也会犯这类错误)。

如果相当一部分工程师不注意内存使用,在很多地方写的代码都有内存错误,但这些错误只在特定条件下爆发,因此最初从表面上看,系统运行还算正常。

但当这些错误累加到一定程度,对系统的危害是非常大的。

因此建议所有的工程师都重视内存使用,养成内存检查的习惯

建议每写完/修改完一个函数,都按照以下流程检查错误

1.6.1.检查内存泄漏

内存泄漏就是,对于动态分配的内存,没有释放

如果写了以下代码

char*pStr=mfw_alloc(10)

mfwHndtim=timCreate();

对应在函数结束前,就应该释放内存

mfw_free(pStr,10)

timDelete(tim)

1.6.2.检查内存重复释放

对已经释放的内存再次释放,就是重复释放

…..

…….

mfw_free(pStr,10)//内存重复释放,可能造成内存错误

1.6.3.检查内存越界

3.1避免数组越界

如intnNum[10]

要确认各种情况下,不可以访问内存nNum[n]n>

=10

比较良好的习惯是用宏来防治越界

如#defineMAX_NUM10

intnNum[MAX_NUM]

for(intI=0;

I<

MAX_NUM;

I++)

访问nNum;

3.2避免字符串越界

●理解c语言中字符串以’\0’(真0)结束,如果一个字符串中最大容纳10的字符,需要分配11个字符长度,如charcStr[MAX_LEN+1],最后一个字符放置’\0’

●分配字符串后,需要立刻把字符串置0

如charcStr[MAX_LEN+1];

memset(cStr,0,MAX_LEN+1)

否则,请看以下代码

inta=strlen(cStr);

此时a的数值不确定,很有可能大于MAX_LEN+1,如果在用a对cStr操作,后果非常严重

●理解所有字符操作函数,都是以’\0’为结束,如

chara[10]={'

1'

'

2'

3'

\0'

4'

};

此时数组中的内容为

31323300340000000000

⏹此时如果调用strlen(a),返回值为3,因为第四个字符为’\0’,第五个字符不予处理

⏹如果执行以下语句

charb[10],

memset(b,0,10)

strcpy(b,a);

此时b的内容为31323300340000000000,即只copy到a的第三个字符

charc[10]={'

strcat(ca);

此时c的内容为31323132330000000000

1.6.4.避免在栈中分配过大内存

我们开发的嵌入式软件,每个task的栈的大小都非常有限(目前mmitask的栈为6k).

栈的使用有以下特点。

●栈有迭加效果,

函数a在栈中分配了1k字节内存

函数b在栈中分配了1k字节内存

函数c在栈中分配了1k字节内存

只调用a|b|c都没有问题,但如果a调用b,b调用c,就可能出错

●一旦出错,非常非常难查

函数中的局部变量分配在栈中,一般来讲,如果一个局部变量大于100个字节,就应该动态分配

错误写法

intfunc1()

charb[100]//b占用100个字节的栈空间,可能诱发栈被破坏

正确写法

char*b=mfw_alloc(100);

1.6.5.注意对指针的使用

对指针的使用规则如下

●初始化为0

●分配一块空间,指针指向该空间

●释放空间,指针重新指向0

代码事例

●初始化

char*pStr=0;

●分配空间

if(pStr==0)//pStr为0,表示其不指向任何动态内存,不要释放

pStr=mfwAlloc(10)

●释放空间

if(pStr!

=0)//pStr不为0,表示其指向动态内存,需要释放

mfwFree(pStr);

pStr=0;

这样我们可以掌握以下原则

●如果某指针为0,则该指针不指向任何动态分配内存。

⏹可以分配内存同时把首地址给该指针,而不会内存泄漏。

⏹如果该指针指向某动态分配内存,释放后该指针指向0,以后不需要再释放内存,防止内存重复释放

●如果某指针不为0,说明该指针指向动态分配内存

⏹如果需要分配内存同时把首地址给该指针,需要先释放该指针指向的原内存,否则会内存泄漏

⏹在离开该指针作用范围前,需要释放该指针指向的动态内存

1.6.6.多线程模式下的内存问题

下面举一个简单的例子说明线程同步, 

对于线程不是很了解的同仁,建议还是读读其它相关数据,至少要理解相关基本概念,如线程和程序的关系等。

inttmp=0;

chartmpChar[10];

voidfunc1()

for(tmp=0;

tmp<

10;

tmp++)

tmpChar[tmp]=tmp;

voidfunc2()

……

tmp=20;

●如果这两个函数在同一个task里顺序执行,不会有问题

●假定func1由task1执行,func2由task2执行.如果func1先被运行,在运行到一半时(如tmp=5时),task1被中断,task2运行,给tmp赋值为20.然后task2休眠,task1接着运行,此时tmp=20,执行以下语句而内存越界

tmpChar[20]=20

这样的问题是比较难查的,可能大多数情况下task1和task2不会互相干扰,只是在特殊情况下才出现问题.

除了全局变量,凡是对所有线程都可见的存储空间(如堆内存和静态变量),都有上述问题。

请采取以下措施,避免多线程编程模式下的内存问题

●尽量避免使用全局变量和静态变量

●如果必须使用全局变量和静态变量,并且该全局变量和静态变量有可能被不同的线程访问,要用信号量等操作系统机制保护

●如果使用回调的方式实现功能,尽量在回调里面发送消息给另外一个线程,另外一个线程收到消息后实现该功能,而不要直接在回调函数里面写功能实现代码。

如线程A向线程B注册了一个回调函数,希望线程B发生特定事件后回调该函数实现某编码功能。

则最好不要在该回调函数里面实现编码功能,回调函数应该只是向线程A发送一个消息,线程A收到该消息后实现编码功能

1.6.7.理解幷遵守平台的内存使用原则

平台本身一般不会发生内存错误(否则该平台不会广泛使用),一般是我们对平台理解的不够透彻导致。

这样做看似比较麻烦,但是熟悉以后,其实非常快的。

同时基本把内存错误都避免了。

1.7.Referencecode

#include<

stdio.h>

intd;

printf("

dddddddd"

);

scanf("

%d"

&

d);

return0;

intfunc2();

string.h>

typedefint(*func)();

voidmem_override()

intarr[10];

memset(arr,0,sizeof(int)*10);

arr[10]=3;

return;

voidstr_len_test()

intstrLen=0;

{

charcStr[10+1];

strLen=strlen(cStr);

//ifyoucallstrcpy(cStr,str1,strLen);

willmemoryoverride

memset(cStr,0,10+1);

}

chara[10]={'

charb[10];

charc[10]={'

strLen=strlen(a);

memset(b,0,10);

strcpy(b,a);

strcat(c,a);

voidstack_override()

inttmp[10000000];

voidmain()

stack_override();

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 院校资料

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1