内存

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

3Sept.2008©NeusoftConfidentialC语言中级内存目标:1)明确内存划分2)了解内存相关库函数3)明确内存使用注意事项4)独立完成编程练习时间:学时教学方法:PPT+练习程序设计的本质所谓程序就是由实现算法的语句来操纵存放在计算机的内存中的数据。可见,了解内存的分配和活动乃是编程者的第一要务。程序设计就是对内存直接或间接地使用。3.1内存划分栈区静态区堆区代码区数据区代码区memory存放程序的代码和常量存放程序的全局变量和静态变量存放程序动态申请的数据存放程序的局部变量和形参分为4个区域:3.1内存划分栈区(stack区)•由系统按栈原则管理•短命,函数执行完则释放。•用户无法干预变量的诞生和消亡#includestdio.hintmain(void){inti=0;charj=1;floatk=2.0f;printf(%d%c%f,i,j,k);return0;}&i0x0012ff7c&j0x0012ff78&k0x0012ff74&iCXX0069:Error:variableneedsstackframe&jCXX0069:Error:variableneedsstackframe&kCXX0069:Error:variableneedsstackframe3.1内存划分voidfun1(void){intn=0;……}voidfun2(void){intn=1;……}intmain(void){intn=0;fun1();fun2();return0;}主函数栈fun1函数栈fun2函数栈#includestdio.hcharcolor='B';voidfirst(void){charcolor;color='R';printf(colorinfirst()is%c\n,color);}voidsecond(void){color='G';printf(colorinsecond()is%c\n,color);}voidmain(void){printf(colorinmain()is%c\n,color);first();printf(colorinmain()is%c\n,color);second();printf(colorinmain()is%c\n,color);}3.1内存划分—分析程序结果1全局变量和局部变量同名时,在函数中引用,局部屏蔽全局!int*fun1(){intj=5;int*p=&j;returnp;}int*fun2(void){intj=10;int*p=&j;returnp;}intmain(){int*p=fun1();fun2();//先注释掉printf(%d\n,*p);return0;}千万不要返回指向栈内存的指针!3.1内存划分—分析程序结果23.1内存划分#includestdio.hvoidfun(void){staticintn;printf(%d\n,n);}intmain(void){fun();return1;}#includestdio.hvoidfun(void){intn;printf(%d\n,n);}intmain(void){fun();return1;}printf(%d\n,n);printf(%d\n,n);静态区(static区)•不按栈原则管理,长命。但局部静态变量仍受“作用域”的制约3.1内存划分—分析结果3#includestdio.hintfunc(void){staticinti=0;return++i;}voidmain(void){inti;i=func();i=func();printf(%d\n,i);}static局部变量只做一次初始化23.1内存划分堆区(heap区)•长命•无名•用户干预变量的诞生和消亡•在程序运行时才动态分配内存•申请可能失败•3.2节详细讨论3.1内存划分代码区(code区)•存有程序的所有执行代码和常量voidfun(void){chara[20]=“helloworld!”;}3.2堆空间的使用C语言的动态内存分配核心函数有:malloc()申请堆内存free()释放堆内存•malloc()函数原型:void*malloc(size_tsize);typedefunsignedintsize_t;功能:从堆内存中分配连续的大小为size字节的内存单元,这些单元没有类型。使用这两个函数必须包含头文件stdlib.h。返回值:若有足够的内存,则返回指向分配的内存空间的首地址(void*类型),否则返回NULL。应用中需要使用(类型*)把返回值强制转换为特定类型3.2堆空间的使用•free()函数原型:voidfree(void*memblock);功能:用来释放被malloc()或calloc()分配的内存空间。注意:传入指向堆内存空间的首地址,例如:voidFun(void){int*p=(int*)malloc(sizeof(int)*10);……free(p);//所释放的是40个字节而非4个字节。……//在此处p依然可以访问,但是容易出现问题}释放的是整个块,而不是指向该块的指针类型的大小。3.2堆空间的使用•free()函数原型:voidfree(void*memblock);功能:用来释放被malloc()或calloc()分配的内存空间。注意:在程序的执行过程中,函数体内的局部指针变量在函数结束时会自动消亡,但是它所指向的动态分配的内存却不会自动释放,需要free()函数来完成该任务。例如:voidFun(void){int*p=(int*)malloc(sizeof(int)*10);……}//函数退栈时,p自动消亡,但堆内存没有释放,//因为没有使用free函数3.2堆空间的合理使用#includestdio.h#includestdlib.h#defineTRUE1intmain(void){char*pstring=NULL;pstring=(char*)malloc(500);if(NULL==pstring){printf(“Insufficientmemoryavailable\n”);exit(1);}else{printf(Spaceallocatedforpathname\n);free(pstring);pstring=NULL;printf(Memoryfreed\n);}returnTRUE;}3.2堆区的使用—分析结果4#includestdio.h#includestdlib.h#includestring.h#defineTRUE1intmain(void){char*p=(char*)malloc(7);strcpy(p,1234567);printf(%s\n,p);free(p+1);returnTRUE;}8p//能否正确打印?//能否正确释放?示例1:数组或指针的下标越界(在VC6.0下演示效果明显)3.3注意事项(重要)#includestdio.h#defineTRUE1intmain(void){inti=0;inta[5]={0};intcount=0;for(i=0;i=5;i++){a[i]=1;printf(执行了%d次循环.\n,++count);}returnTRUE;}//结果如何?示例2:内存释放不代表指针消亡3.3注意事项free(p);p=NULL;示例3:指针消亡不代表内存释放int*MyMalloc(intn){int*p=NULL;p=(int*)malloc(sizeof(int)*n);returnp;//假定再也没释放堆区内存}内存被释放了,并不表示指向这块内存的指针会消亡或者置为了NULL。3.3注意事项示例4:不能只释放块的一部分空间#defineTRUE1intmain(void){int*p=(int*)malloc(sizeof(int)*10);if(p!=NULL){//你的代码}else{//给出错误信息}returnTRUE;}free(p+1);free(p-1);示例5:使用野指针的危害3.3注意事项#includestdio.h#includestdlib.h#includestring.hintmain(void){char*p=(char*)malloc(sizeof(char)*10);//…..省略了申请是否成功的处理char*q=NULL;strcpy(p,Neusoft);free(p);q=(char*)malloc(sizeof(char)*10);strcpy(q,Neusoft);if(p!=NULL)*p='O';printf(%s\n,q);return1;}//注意这儿没有p=NULL;NeupqO3.3注意事项•示例6:内存泄漏#includestdlib.h#includestdio.hintmain(){char*p=NULL;p=(char*)malloc(10);//…..省略了申请是否成功的处理p=“Hello”;printf(%s\n,p);free(p);return0;}小结•掌握内存区域的划分及其属性:•堆空间相关函数malloc()、calloc()、free()的函数参数、返回值、函数功能•使用堆空间的注意事项申请不一定成功,使用前先判断用完后空间要释放指针要置NULL小结•stack、static、heap三者的区别仅在于效率。前者有最快的速度、最短的寿命,这是最有效率的使用,但必须在编译前就决定下来,不能再变,因此它没有灵活性。这个区不可以动态申请,不属动态区。•静态变量仅比栈变量生存期长,且能被初始化,它也同于栈变量没有灵活性。•堆内存最灵活,它是动态分配的,也就是可以在程序运行中即时申请,且管理原则是按链表管理的,于是时耗远大于栈,这是灵活的代价。这个区才是真正的动态区。分配时机/分配责任释放时机/释放责任静态内存这种内存在编译时就规划好了,在程序运行期间一直存在。是由编译器负责分配的。程序退出时释放,不用程序员参与。栈内存函数调用临时创建的。为函数返回、函数形参、函数中定义的局部变量在栈里申请空间。函数退出时释放,不用程序员参与。堆内存程序员根据需要用malloc等函数创建的内存。在适当时机由程序员用free释放。小结练习1打印文字练习。随机产生要录入的文字,用户输入录入个数,计算用户录入文字耗时。实现一个“可变长二维数组”,这个二维数组的行数可由输入决定,每行的元素个数仍可由输入决定。每个数组元素值都是1.执行结果如下:请输入行数:5请输入第1行的元素个数:20请输入第2行的元素个数:34请输入第3行的元素个数:17请输入第4行的元素个数:9请输入第5行的元素个数:25111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111Pressanykeytocontinue练习2—有难度111111111111111p_array练习—锯齿数组提示谢谢!

1 / 29
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功