单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,完整版课件,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,二级,三级,四级,五级,完整版课件,*,C,语言的深度挖掘(一),变量的表示与存储问题,1,完整版课件,C 语言的深度挖掘(一)变量的表示与存储问题1完整版课件,是否入门?,2,完整版课件,是否入门?2完整版课件,改进,3,完整版课件,改进3完整版课件,有错吗?,4,完整版课件,有错吗?4完整版课件,为什么在每个头文件都能见到,5,完整版课件,为什么在每个头文件都能见到5完整版课件,哪个执行效率高?,6,完整版课件,哪个执行效率高?6完整版课件,浮点数的内存表示问题,7,完整版课件,浮点数的内存表示问题7完整版课件,无符号整数与有符号整数,8,完整版课件,无符号整数与有符号整数8完整版课件,可以少传一个参数吗?,9,完整版课件,可以少传一个参数吗?9完整版课件,为什么有时相同有时不同?,12,15,12,12,改成char a10;,会输出什么?,10,完整版课件,为什么有时相同有时不同?1212改成char a10;1,结构体变量的内存表示,11,完整版课件,结构体变量的内存表示11完整版课件,联合类型变量的内存表示,12,完整版课件,联合类型变量的内存表示12完整版课件,实际应用的例子,13,完整版课件,实际应用的例子13完整版课件,位域,14,完整版课件,位域14完整版课件,应用位域的例子段描述符,15,完整版课件,应用位域的例子段描述符15完整版课件,C/C+,程序运行时的内存结构,全局变量、用static修饰的局部变量都存储在静态数据区。,程序指令和大部分字面常量都存储在代码区。,大部分函数的形参和局部变量都存储在栈区。,程序中动态分配的内存都存储在堆区。,一小部分函数形参和局部变量存储在CPU寄存器组中。,静态数据区,代码区,栈区,堆区,CPU寄存器组,常量数据区,已初始化区,未初始化区,16,完整版课件,C/C+程序运行时的内存结构全局变量、用static修饰的,变量的生存期,把程序运行时一个变量占有内存空间的时间段称为该变量的,生存期,。C+把变量的生存期分为:,静态,、,自动,和,动态,三种。,静态生存期,:全局变量都具有静态生存期,它们的内存空间从程序开始执行时就进行分配,直到程序结束才被收回。,自动生存期,:局部变量和函数形参一般都具有自动生存期,它们的内存空间在程序执行到定义它们的复合语句(包括函数体)时才分配,当定义它们的复合语句执行结束时内存被收回。,动态生存期,:具有动态生存期的变量的生存时间是由程序员自由控制的,其内存空间用new操作符分配,用delete回收。,在定义局部变量时,可以为它们加上存储类修饰符,auto、static,和,register,来指出它们的生存期。,定义为static存储类型的局部变量具有静态生存期,它们也被存放在静态数据区。,17,完整版课件,变量的生存期 把程序运行时一个变量占有内存空间的时间段称为该,关键字,volatile,的作用,18,完整版课件,关键字volatile的作用18完整版课件,main函数为空居然也有输出?,19,完整版课件,main函数为空居然也有输出?19完整版课件,关键字,extern,的作用,错了!,20,完整版课件,关键字extern的作用错了!20完整版课件,系统栈与过程调用,局部变量 var_main,参数 arg_A2=1,返回地址,其他信息,局部变量 var_A2,参数 arg_B2=3,返回地址,其他信息,局部变量 var_A1,局部变量 var_B2,.,局部变量 var_B1,.,栈底,栈顶,参数arg_A1=2,参数 arg_B1=4,func_B,的栈帧,func_A,的栈帧,main,的栈帧,21,完整版课件,系统栈与过程调用局部变量 var_main参数 arg_A2,有问题吗?,22,完整版课件,有问题吗?22完整版课件,有问题吗?,23,完整版课件,有问题吗?23完整版课件,输出什么?,24,完整版课件,输出什么?24完整版课件,存储位置是否相同?,25,完整版课件,存储位置是否相同?25完整版课件,输出什么?,26,完整版课件,输出什么?26完整版课件,输出什么?,27,完整版课件,输出什么?27完整版课件,常量成了变量?,28,完整版课件,常量成了变量?28完整版课件,堆内存管理方法初探,int*p1=(int*)malloc(sizeof(int);,char*p2=(char*)malloc(sizeof(char);,free(p1);,free(p2);,1000,大,基地址,长度,1000,100,自由内存区表,基地址,长度,占用内存区表,29,完整版课件,堆内存管理方法初探int*p1=(int*)mall,堆内存管理方法初探,int*p1=(int*)malloc(sizeof(int);,char*p2=(char*)malloc(sizeof(char);,free(p1);,free(p2);,1000,大,基地址,长度,1004,96,自由内存区表,基地址,长度,1000,4,占用内存区表,30,完整版课件,堆内存管理方法初探int*p1=(int*)mall,堆内存管理方法初探,int*p1=(int*)malloc(sizeof(int);,char*p2=(char*)malloc(sizeof(char);,free(p1);,free(p2);,1000,大,基地址,长度,1004,6,100B,89,自由内存区表,基地址,长度,1000,4,100A,1,占用内存区表,100A,最先适配算法,最佳适配算法,31,完整版课件,堆内存管理方法初探int*p1=(int*)mall,堆内存管理方法初探,int*p1=(int*)malloc(sizeof(int);,char*p2=(char*)malloc(sizeof(char);,free(p1);,free(p2);,1000,大,基地址,长度,1000,10,100B,89,自由内存区表,基地址,长度,1000,4,100A,1,占用内存区表,100A,堆的紧缩问题,32,完整版课件,堆内存管理方法初探int*p1=(int*)mall,堆内存管理方法初探,int*p1=(int*)malloc(sizeof(int);,char*p2=(char*)malloc(sizeof(char);,free(p1);,free(p2);,1000,大,基地址,长度,1000,100,自由内存区表,基地址,长度,1000,4,100A,1,占用内存区表,100A,33,完整版课件,堆内存管理方法初探int*p1=(int*)mall,使用malloc和free的注意事项,刚刚分配的动态内存的初始值是不确定的,不能对同一指针(地址)连续两次进行free操作,不能对指向静态内存区(全局变量)或栈内存区(局部变量)的指针应用free(但可以对空指针NULL应用free)。,对一个指针应用free之后,它的值不会改变,但它指向了一个无效的内存区,这时称该指针为“悬空指针”。,如果没有及时释放某块动态内存,并且将指向它的指针指向了别处,就会造成“内存泄漏”。,执行malloc和free函数有一定的代价,所以对于较小的变量不应该放在动态内存之中,并且尽量避免频繁地分配和释放动态内存。,34,完整版课件,使用malloc和free的注意事项刚刚分配的动态内存的初始,使用堆内存时的常见错误,内存分配未成功,却使用了它。,内存分配虽然成功,但是尚未初始化就引用它。(误认为初始值为0),内存分配成功并且已经初始化,但操作越过了内存的边界。,忘记了释放内存,造成内存泄露。,释放了内存却继续使用它。,35,完整版课件,使用堆内存时的常见错误内存分配未成功,却使用了它。35完整版,关于悬空指针,一个指针变量,如果不为NULL且没有指向有效的内存地址,都称为“悬空指针”,通过悬空指针访问其指向的内存区会使程序产生不可预知的错误。,如何避免悬空指针:,定义指针变量时坚持对其进行正确的初始化,在用free或delete释放内存之后,应及时将相应的指针置为NULL,36,完整版课件,关于悬空指针一个指针变量,如果不为NULL且没有指向有效的内,悬空指针的例子(一),void,somefuncion(),int,*p;,.,*p=7;,.,void,somefuncion(),int,*p=NULL;,/正确地进行初始化,.,*p=7;,.,37,完整版课件,悬空指针的例子(一)void somefuncion()vo,悬空指针的例子(二),int,main(),int,*p=NULL;,p=(,int,*)malloc(,sizeof,(,int,);,*p=5;,free(p);,/do something,*p=7;,printf(%d,*p);,free(p);,p=NULL;,38,完整版课件,悬空指针的例子(二)int main()free(p);3,内存泄漏的例子(一),void,MyFunction(,int,nSize),char,*p=,new,char,nSize;,if,(!SomeFunc(),printf(“Error”);,return,;,/using the string pointed by p;,delete,p;,39,完整版课件,内存泄漏的例子(一)void MyFunction(int,内存泄漏的例子(二),char,*TransToEng(,const,char,*inputStr)/,将中文翻译成英文,char,*outputStr=(,char,*)malloc();,/*翻译*/,return,outputStr;,int,main(),char,*chineseStr=欢迎光临;,char,*englishStr=TransToEng(欢迎光临);,printf(%s,englishStr);,40,完整版课件,内存泄漏的例子(二)char*TransToEng(con,如何避免内存泄漏,运行检测法,定义自己的malloc和free函数,或者对new和delete进行重载,在运行时跟踪记录动态内存的分配和释放情况,利用专用的检测工具,如BoundsChecker、Purify和Performance Monitor,利用复杂的程序设计技术(C+),智能指针技术,为C+增加垃圾回收机制(可参考C+编程艺术艺术),41,完整版课件,如何避免内存泄漏运行检测法41完整版课件,感谢亲观看此幻灯片,此课件部分内容来源于网络,,如有侵权请及时联系我们删除,谢谢配合!,感谢亲观看此幻灯片,此课件部分内容来源于网络,,