2022年C++内存管理详解.docx
《2022年C++内存管理详解.docx》由会员分享,可在线阅读,更多相关《2022年C++内存管理详解.docx(29页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、精品学习资源C+内存治理详解程序员们经常编写内存治理程序,往往提心吊胆;假如不想触雷,唯独的解决方法就是发觉全部潜伏的地雷并且排除它们,躲是躲不了的;本文的内容比一般教科书的要深化得多,读者需细心阅读,做到真正地通晓内存管理;1、内存支配方式内存支配方式有三种:(1) )从静态储备区域支配;内存在程序编译的时候就已经支配好,这块内存在程序的整个运行期间都存在;例如全局变量, static 变量;(2) )在栈上创建;在执行函数时,函数内局部变量的储备单元都可以在栈上创建,函数执行终止时这些储备单元自动被释放;栈内存支配运算内置于处理器的指令集中,效率很高,但是支配的内存容量有限;(3) ) 从
2、堆上支配,亦称动态内存支配;程序在运行的时候用malloc 或 new申请任意多少的内存, 程序员自己负责在何时用 free或 delete释放内存;动态内存的生存期由我们准备,使用特殊灵敏,但问题也最多;2、常见的内存错误及其计策发生内存错误是件特殊麻烦的事情;编译器不能自动发觉这些错误,通常是在程序运行时才能捕捉到;而这些错误大多没有明显的症状,时隐时现,增欢迎下载精品学习资源加了改错的难度; 有时用户怒气冲冲地把你找来, 程序却没有发生任何问题, 你一走,错误又发作了;常见的内存错误及其计策如下:*内存支配未成功,却使用了它;编程新手常犯这种错误,由于他们没有意识到内存支配会不成功;常用
3、 解决方法是, 在使用内存之前检查指针是否为NULL;假如指针 p 是函数的参数,那么在函数的入口处用 assertp.=NULL进行检查;假如是用 malloc 或 new来申请内存,应当用 ifp=NULL或ifp.=NULL进行防错处理;* 内存支配虽然成功,但是尚未初始化就引用它;犯这种错误主要有两个起因:一是没有初始化的观念;二是误以为内存的缺省初值全为零,导致引用初值错误(例如数组);内存的缺省初值究竟是什么并没有统一的标准,尽管有些时候为零值,我们宁可信其无不行信其有;所以无论用何种方式创建数组,都别忘了赋初值,即便是赋零值也不行省略,不要嫌麻烦;* 内存支配成功并且已经初始化,
4、但操作越过了内存的边界;例如在使用数组经经常发生下标“多1”或者“少 1”的操作;特殊是在 for循环语句中,循环次数很简洁搞错,导致数组操作越界;* 遗忘了释放内存,造成内存泄露;欢迎下载精品学习资源含有这种错误的函数每被调用一次就丢失一块内存;刚开头时系统的内存充分, 你看不到错误; 终有一次程序突然死掉, 系统显现提示: 内存耗尽;动态内存的申请与释放必需配对, 程序中 malloc 与 free 的使用次数确定要相同,否就确定有错误( new/delete同理);* 释放了内存却连续使用它;有三种情形:(1) )程序中的对象调用关系过于复杂,实在难以搞清楚某个对象究竟是否已经释放了内存
5、,此时应当重新设计数据结构,从根本上解决对象治理的纷乱局面;(2) )函数的 return语句写错了,留意不要返回指向“栈内存”的“指针”或者“引用”,由于该内存在函数体终止时被自动销毁;(3) )使用 free或 delete释放了内存后,没有将指针设置为NULL;导致产生“野指针”;【规章 1】用 malloc 或 new申请内存之后, 应当马上检查指针值是否为NULL;防止使用指针值为 NULL的内存;【规章 2】不要遗忘为数组和动态内存赋初值;防止将未被初始化的内存作为右值使用;欢迎下载精品学习资源【规章 3】防止数组或指针的下标越界,特殊要当心发生“多1”或者“少 1”操作;【规章
6、4】动态内存的申请与释放必需配对,防止内存泄漏;【规章 5】用 free 或 delete释放了内存之后, 马上将指针设置为 NULL,防止产生“野指针”;3、指针与数组的对比C+/C程序中,指针和数组在不少地方可以相互替换着用,让人产生一种错觉,以为两者是等价的;数组要么在静态储备区被创建(如全局数组),要么在栈上被创建;数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变, 只有数组的内容可以转变;指针可以随时指向任意类型的内存块,它的特点是“可变”,所以我们常用指针来操作动态内存;指针远比数组灵敏,但也更危险;下面以字符串为例比较指针与数组的特性;3.1 修改内容示例 3-
7、1 中,字符数组 a 的容量是 6 个字符,其内容为 hello ;a 的内容可以转变,如 a0=X;指针 p 指向常量字符串“ world ”(位于静态欢迎下载精品学习资源储备区,内容为 world ),常量字符串的内容是不行以被修改的;从语法上看,编译器并不觉得语句p0=X有什么不妥,但是该语句妄图修改常量字符串的内容而导致运行错误;char a =“hello ”;a0 =X;cout a endl;char *p =“ world ”; /留意 p 指向常量字符串p0 =X; /编译器不能发觉该错误cout p endl;示例 3.1修改数组和指针的内容3.2 内容复制与比较不能对数组
8、名进行直接复制与比较;示例7-3-2 中,如想把数组 a 的内容复制给数组 b,不能用语句 b = a ,否就将产生编译错误;应当用标准库函数 strcpy进行复制;同理,比较 b 和 a 的内容是否相同, 不能用 ifb=a 来判定,应当用标准库函数 strcmp 进行比较;语句 p = a并不能把 a 的内容复制指针 p,而是把 a 的地址赋给了 p;要想复制 a 的内容,可以先用库函数 malloc 为 p 申请一块容量为欢迎下载精品学习资源strlena+1个字符的内存,再用 strcpy进行字符串复制;同理,语句ifp=a比较的不是内容而是地址,应当用库函数strcmp 来比较;/数
9、组char a = hello; char b10;strcpyb, a; /不能用 b = a;ifstrcmpb, a = 0 /不能用 if b = a/指针int len = strlena;char *p = char *mallocsizeofchar*len+1; strcpyp,a; /不要用 p = a;ifstrcmpp, a = 0 /不要用 if p = a示例 3.2数组和指针的内容复制与比较3.3 运算内存容量用运算符 sizeof可以运算出数组的容量(字节数);示例 7-3-3 (a)中, sizeofa的值是 12(留意别忘了);指针 p 指向a,但是 size
10、ofp的值却是 4;这是由于 sizeofp得到的是一个指针变量欢迎下载精品学习资源的字节数,相当于 sizeofchar*,而不是 p 所指的内存容量; C+/C 语言没有方法知道指针所指的内存容量,除非在申请内存时记住它;留意当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针;示例 7-3-3 (b)中,不论数组 a 的容量是多少, sizeofa始终等于sizeofchar *;char a = hello world; char *p = a;cout sizeofa endl; / 12字节cout sizeofp endl; / 4字节示例 3.3 (a) 运算数组和指针
11、的内存容量void Funcchar a100cout sizeofa endl; / 4字节而不是 100 字节示例 3.3 (b) 数组退化为指针欢迎下载精品学习资源4、指针参数是如何传递内存的?假如函数的参数是一个指针, 不要希望用该指针去申请动态内存; 示例 7-4-1 中, Test 函数的语句 GetMemorystr, 200 并没有使 str 获得期望的内存, str 照旧是 NULL,为什么 .void GetMemorychar *p, int nump = char *mallocsizeofchar * num;void Testvoidchar *str = NULL
12、;GetMemorystr, 100; / str仍然为 NULL strcpystr, hello; /运行错误示例 4.1试图用指针参数申请动态内存毛病出在函数 GetMemory中;编译器总是要为函数的每个参数制作临时副本, 指针参数 p 的副本是 _p ,编译器使 _p = p ;假如函数体内的程序修改了 _p 的内容,就导致参数 p 的内容作相应的修改;这就是指针可以用作输出参数的缘由;在本例中, _p 申请了新的内存, 只是把 _p 所指的内存地址转变了,欢迎下载精品学习资源但是 p 丝毫未变;所以函数 GetMemory并不能输出任何东西;事实上,每执行一次 GetMemory就
13、会泄露一块内存,由于没有用 free释放内存;假如非得要用指针参数去申请内存, 那么应当改用“指向指针的指针” , 见示例 4.2 ;void GetMemory2char *p, int num*p = char *mallocsizeofchar * num;void Test2voidchar *str = NULL;GetMemory2&str, 100; /留意参数是 &str ,而不是 str strcpystr, hello;cout str endl; freestr;示例 4.2 用指向指针的指针申请动态内存欢迎下载精品学习资源由于“指向指针的指针”这个概念不简洁懂得,我们可
14、以用函数返回值来传递动态内存;这种方法更加简洁,见示例4.3 ;char *GetMemory3int numchar *p = char *mallocsizeofchar * num; return p;void Test3voidchar *str = NULL;str = GetMemory3100; strcpystr, hello; cout str endl; freestr;示例 4.3用函数返回值来传递动态内存用函数返回值来传递动态内存这种方法虽然好用,但是经常有人把return语句用错了;这里强调不要用 return语句返回指向“栈内存”的指针,因欢迎下载精品学习资源为该内
15、存在函数终止时自动消亡,见示例4.4 ;char *GetStringvoidchar p = hello world;return p; /编译器将提出警告void Test4voidchar *str = NULL;str = GetString; / str的内容是垃圾cout str endl;示例 4.4 return语句返回指向“栈内存”的指针用调试器逐步跟踪 Test4 ,发觉执行 str= GetString语句后 str不再是 NULL指针,但是 str的内容不是“ hello world”而是垃圾;假如把示例 4.4 改写成示例 4.5 ,会怎么样?欢迎下载精品学习资源ch
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 2022 C+ 内存 管理 详解
限制150内