C++内存管理详解1121.docx





《C++内存管理详解1121.docx》由会员分享,可在线阅读,更多相关《C++内存管理详解1121.docx(26页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、C+内存管理详解程序员们经常编写内存管理程序,往往提心吊胆。如果不想触雷,唯一的解决办法就是发现所有潜伏的地雷并且排除它们,躲是躲不了的。本文的内容比一般教科书的要深入得多,读者需细心阅读,做到真正地通晓内存管理。 1、内存分配方式内存分分配方式式有三种种:(1)从静静态存储储区域分分配。内内存在程程序编译译的时候候就已经经分配好好,这块块内存在在程序的的整个运运行期间间都存在在。例如如全局变变量,sstattic变变量。(2)在在栈上创创建。在在执行函函数时,函函数内局局部变量量的存储储单元都都可以在在栈上创创建,函函数执行行结束时时这些存存储单元元自动被被释放。栈栈内存分分配运算算内置于于
2、处理器器的指令令集中,效效率很高高,但是是分配的的内存容容量有限限。(3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。2、常见的的内存错错误及其其对策发发生内存存错误是是件非常常麻烦的的事情。编编译器不不能自动动发现这这些错误误,通常常是在程程序运行行时才能能捕捉到到。而这这些错误误大多没没有明显显的症状状,时隐隐时现,增增加了改改错的难难度。有有时用户户怒气冲冲冲地把把你找来来,程序序却没有有发生任任何问题题,你一一走,错错误又发发作了。
3、 常见的内存错误及其对策如下:* 内内存分配配未成功功,却使使用了它它。编程新新手常犯犯这种错错误,因因为他们们没有意意识到内内存分配配会不成成功。常常用解决决办法是是,在使使用内存存之前检检查指针针是否为为NULLL。如如果指针针p是函数数的参数数,那么么在函数数的入口口处用aasseert(p!=NULLL)进进行检查。如如果是用用malllocc或neww来申请请内存,应应该用iif(pp=NNULLL) 或或if(p!=NULLL)进进行防错错处理。* 内内存分配配虽然成成功,但但是尚未未初始化化就引用用它。犯这种种错误主主要有两两个起因因:一是是没有初初始化的的观念;二是误误以为内内
4、存的缺缺省初值值全为零零,导致致引用初初值错误误(例如如数组)。内内存的缺缺省初值值究竟是是什么并并没有统统一的标标准,尽尽管有些些时候为为零值,我我们宁可可信其无无不可信信其有。所所以无论论用何种种方式创创建数组组,都别别忘了赋赋初值,即即便是赋赋零值也也不可省省略,不不要嫌麻麻烦。* 内内存分配配成功并并且已经经初始化化,但操操作越过过了内存存的边界界。例如在在使用数数组时经经常发生生下标“多1”或者者“少1”的操操作。特特别是在在forr循环语语句中,循循环次数数很容易易搞错,导导致数组组操作越越界。* 忘忘记了释释放内存存,造成成内存泄泄露。含有这这种错误误的函数数每被调调用一次次就丢
5、失失一块内内存。刚刚开始时时系统的的内存充充足,你你看不到到错误。终终有一次次程序突突然死掉掉,系统统出现提提示:内内存耗尽尽。动态内内存的申申请与释释放必须须配对,程程序中mmallloc与与freee的使使用次数数一定要要相同,否否则肯定定有错误误(neew/ddeleete同同理)。* 释释放了内内存却继继续使用用它。有有三种情情况:(1)程程序中的的对象调调用关系系过于复复杂,实实在难以以搞清楚楚某个对对象究竟竟是否已已经释放放了内存存,此时时应该重重新设计计数据结结构,从从根本上上解决对对象管理理的混乱乱局面。(2)函函数的rretuurn语语句写错错了,注注意不要要返回指指向“栈内
6、存存”的“指针”或者“引用”,因为为该内存存在函数数体结束束时被自自动销毁毁。(3)使使用frree或或delletee释放了了内存后后,没有有将指针针设置为为NULLL。导导致产生生“野指针针”。【规则则1】用maallooc或neww申请内内存之后后,应该该立即检检查指针针值是否否为NUULL。防防止使用用指针值值为NUULL的的内存。【规则则2】不要要忘记为为数组和和动态内内存赋初初值。防防止将未未被初始始化的内内存作为为右值使使用。【规则则3】避免免数组或或指针的的下标越越界,特特别要当当心发生生“多1”或者者“少1”操作作。【规则则4】动态态内存的的申请与与释放必必须配对对,防止止内
7、存泄泄漏。【规则则5】用frree或或delletee释放了了内存之之后,立立即将指指针设置置为NUULL,防防止产生生“野指针针”。3、指针与与数组的的对比C+/C程程序中,指指针和数数组在不不少地方方可以相相互替换换着用,让让人产生生一种错错觉,以以为两者者是等价价的。数组要要么在静静态存储储区被创创建(如如全局数数组),要要么在栈栈上被创创建。数数组名对对应着(而而不是指指向)一一块内存存,其地地址与容容量在生生命期内内保持不不变,只只有数组组的内容容可以改改变。指针可可以随时时指向任任意类型型的内存存块,它它的特征征是“可变”,所以以我们常常用指针针来操作作动态内内存。指指针远比比数组
8、灵灵活,但但也更危危险。下面以以字符串串为例比比较指针针与数组组的特性性。3.11 修改改内容示例33-1中中,字符符数组aa的容量量是6个字符符,其内内容为hhelllo。a的内容容可以改改变,如如a00= X。指针针p指向常常量字符符串“worrld”(位于静态存储区,内容为world),常量字符串的内容是不可以被修改的。从语法上看,编译器并不觉得语句 p0= X有什么不妥,但是该语句企图修改常量字符串的内容而导致运行错误。char a = “hello”;a0 = X;cout a endl;char *p = “world”; / 注意p指向常量字符串p0 = X; / 编译器不能发现
9、该错误cout p endl;示例3.1 修改数组和指针的内容 3.2 内内容复制制与比较较不能对对数组名名进行直直接复制制与比较较。示例例7-33-2中中,若想想把数组组a的内容容复制给给数组bb,不能能用语句句 b = aa ,否否则将产产生编译译错误。应应该用标标准库函函数sttrcppy进行行复制。同同理,比比较b和a的内容容是否相相同,不不能用iif(bb=aa) 来来判断,应应该用标标准库函函数sttrcmmp进行行比较。语句pp = a 并并不能把把a的内容容复制指指针p,而是是把a的地址址赋给了了p。要想想复制aa的内容容,可以以先用库库函数mmallloc为为p申请一一块容量
10、量为sttrleen(aa)+11个字符符的内存存,再用用strrcpyy进行字字符串复复制。同同理,语语句iff(p=a) 比较较的不是是内容而而是地址址,应该该用库函函数sttrcmmp来比比较。/ 数组组chaar aa = helllo;chhar b110;strrcpyy(b, a); / 不不能用 b = a;if(strrcmpp(b, a) = 0) / 不能能用 iif (b = aa)/ 指针针intt leen = sttrleen(aa);ccharr *pp = (chhar *)mmallloc(sizzeoff(chhar)*(llen+1);sttrcppy(
11、pp,a); / 不不要用 p = a;if(strrcmpp(p, a) = 0) / 不要要用 iif (p = aa)示示例3.2 数数组和指指针的内内容复制制与比较较 3.3 计算内内存容量量用运算算符siizeoof可以以计算出出数组的的容量(字字节数)。示例7-3-3(a)中,sizeof(a)的值是12(注意别忘了)。指针p指向a,但是 sizeof(p)的值却是4。这是因为sizeof(p)得到的是一个指针变量的字节数,相当于sizeof(char*),而不是p所指的内存容量。 C+/C语言没有办法知道指针所指的内存容量,除非在申请内存时记住它。 注意当数组作为函数的参数进行传
12、递时,该数组自动退化为同类型的指针。示例7-3-3(b)中,不论数组a的容量是多少,sizeof(a)始终等于sizeof(char *)。char a = heelloo woorldd;ccharr *pp = a;ccoutt sizzeoff(a) enndl; / 122字节coout ssizeeof(p) enddl; / 4字节节示示例3.3(a) 计算数数组和指指针的内内存容量量 voidd Fuunc(chaar aa1000)coout ssizeeof(a) enddl; / 4字节节而不是是1000字节示示例3.3(b) 数组退退化为指指针4、指针参参数是如如何传递递
13、内存的的? 如果函函数的参参数是一一个指针针,不要要指望用用该指针针去申请请动态内内存。示示例7-4-11中,Teest函函数的语语句GeetMeemorry(sstr, 2000)并并没有使使strr获得期期望的内内存,sstr依依旧是NNULLL,为什什么?voiid GGetMMemoory(chaar *p, intt nuum)p = (chaar *)maallooc(ssizeeof(chaar) * nnum);voiid TTestt(vooid)chhar *sttr = NUULL;GettMemmoryy(sttr, 1000); / strr 仍然然为 NNULLLs
14、trrcpyy(sttr, heelloo); / 运行行错误示例44.1 试图用用指针参参数申请请动态内内存 毛病出在在函数GGetMMemoory中中。编译译器总是是要为函函数的每每个参数数制作临临时副本本,指针针参数pp的副本本是 _p,编编译器使使 _pp = p。如如果函数数体内的的程序修修改了_p的内内容,就就导致参参数p的内容容作相应应的修改改。这就就是指针针可以用用作输出出参数的的原因。在在本例中中,_pp申请了了新的内内存,只只是把 _p所所指的内内存地址址改变了了,但是是p丝毫未未变。所所以函数数GettMemmoryy并不能能输出任任何东西西。事实实上,每每执行一一次Ge
15、etMeemorry就会会泄露一一块内存存,因为为没有用用freee释放放内存。如果非非得要用用指针参参数去申申请内存存,那么么应该改改用“指向指指针的指指针”,见示示例4.2。voiid GGetMMemoory22(chhar *pp, iint numm)*pp = (chhar *)mmallloc(sizzeoff(chhar) * numm);voiid TTestt2(vvoidd)chhar *sttr = NUULL;GeetMeemorry2(&sttr, 1000); / 注意参参数是 &sttr,而而不是sstrstrrcpyy(sttr, heelloo);coout
16、 sstr enddl;freee(sstr);示例44.2用用指向指指针的指指针申请请动态内内存 由于“指向指指针的指指针”这个概概念不容容易理解解,我们们可以用用函数返返回值来来传递动动态内存存。这种种方法更更加简单单,见示示例4.3。char *GeetMeemorry3(intt nuum)chhar *p = (chaar *)maallooc(ssizeeof(chaar) * nnum);rretuurn p;voiid TTestt3(vvoidd)chhar *sttr = NUULL;sttr = GeetMeemorry3(1000);strrcpyy(sttr, hee
17、lloo);coout sstr enddl;freee(sstr);示例例4.33 用函函数返回回值来传传递动态态内存 用函数返返回值来来传递动动态内存存这种方方法虽然然好用,但但是常常常有人把把retturnn语句用用错了。这这里强调调不要用用retturnn语句返返回指向向“栈内存存”的指针针,因为为该内存存在函数数结束时时自动消消亡,见见示例44.4。chaar *GettStrringg(vooid)chhar p = heelloo woorldd;retturnn p; / 编译器器将提出出警告voiid TTestt4(vvoidd)chhar *sttr = NUULL;st
18、tr = GeetSttrinng(); / sstr 的内容容是垃圾圾coout sstr enddl;示例44.4 retturnn语句返返回指向向“栈内存存”的指针针 用调试试器逐步步跟踪TTestt4,发发现执行行strr = GettStrringg语句后后strr不再是是NULLL指针针,但是是strr的内容容不是“helllo worrld”而是垃垃圾。如如果把示示例4.4改写写成示例例4.55,会怎怎么样?char *GeetSttrinng2(voiid)chhar *p = helllo worrld;rretuurn p;voiid TTestt5(vvoidd)chha
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C+ 内存 管理 详解 1121

限制150内