内存分配方式有三种:
(1)
个运行期间都存在。例如全局变量,static变量。
(2)
执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很
高,但是分配的内存容量有限。
(3)
内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,
使用非常灵活,但问题也最多。
7.2常见的内存错误及其对策
才能捕捉到。而这些错误大多没有明显的症状,时隐时现,增加了改错的难度。有时用户
怒气冲冲地把你找来,程序却没有发生任何问题,你一走,错误又发作了。
常见的内存错误及其对策如下:
*
编程新手常犯这种错误,因为他们没有意识到内存分配会不成功。常用解决办法是,在使
用内存之前检查指针是否为NULL。如果指针p是函数的参数,那么在函数的入口处用asser
t(p!=NULL)进行检查。如果是用malloc或new来申请内存,应该用if(p==NULL)
ULL)进行防错处理。*
犯这种错误主要有两个起因:一是没有初始化的观念;二是误以为内存的缺省初值全为零
,导致引用初值错误(例如数组)。
内存的缺省初值究竟是什么并没有统一的标准,尽管有些时候为零值,我们宁可信其无不
可信其有。所以无论用何种方式创建数组,都别忘了赋初值,即便是赋零值也不可省略,
不要嫌麻烦。
*
例如在使用数组时经常发生下标“多1”或者“少1”的操作。特别是在for循环语句中,循
环次数很容易搞错,导致数组操作越界。
*
含有这种错误的函数每被调用一次就丢失一块内存。刚开始时系统的内存充足,你看不到
错误。终有一次程序突然死掉,系统出现提示:内存耗尽。
动态内存的申请与释放必须配对,程序中malloc与free的使用次数一定要相同,否则肯定
有错误(new/delete同理)。
*
有三种情况:
(1)程序中的对象调用关系过于复杂,实在难以搞清楚某个对象究竟是否已经释放了内存
,此时应该重新设计数据结构,从根本上解决对象管理的混乱局面。
(2)函数的return语句写错了,注意不要返回指向“栈内存”的“指针”或者“引用”,
因为该内存在函数体结束时被自动销毁。
(3)使用free或delete释放了内存后,没有将指针设置为NULL。导致产生“野指针”。
*
用指针值为NULL的内存。
*
用。
*
*
*
指针”。
7.3指针与数组的对比
是等价的。
是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变。
指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来操作动
态内存。指针远比数组灵活,但也更危险。
下面以字符串为例比较指针与数组的特性。
7.3.1
0]=
符串的内容是不可以被修改的。从语法上看,编译器并不觉得语句p[0]=
但是该语句企图修改常量字符串的内容而导致运行错误。
char
a[0]
cout
char
p[0]
cout
示例7-3-1
7.3.2
能用语句
b和a的内容是否相同,不能用if(b==a)
以先用库函数malloc为p申请一块容量为strlen(a)+1个字符的内存,再用strcpy进行字符
串复制。同理,语句if(p==a)
...