第七章 内存管理

7.1 内存分配方式

(1)从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。

(2)在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

(3)从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。

7.2常见的内存错误及其对策

  • 内存分配未成功,却使用了它

内存分配会不成功,通常的解决方法是在使用内存前检查指针是否为NULL。如果指针p是函数的参数,那么在函数的入口处用assert(p != NULL)进行防错处理。

  • 内存分配虽然成功,但是尚未初始化就引用它。
    犯这种错误主要有两个起因:一是没有初始化的观念;二是误以为内存的缺省初值

全为零,导致引用初值错误(例如数组)。

  • 内存分配成功并且已经初始化,但操作越过了内存的边界。
  • 忘记了释放内存,造成内存泄露。
  • 释放了内存却继续使用它。

【规则7-2-1】用 malloc 或 new 申请内存之后,应该立即检查指针值是否为 NULL。防止使用指针值为 NULL 的内存。

【规则7-2-2】不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右值使用。

【规则7-2-3】避免数组或指针的下标越界,特别要当心发生“多1”或者“少1”操作。

【规则7-2-4】动态内存的申请与释放必须配对,防止内存泄漏。

【规则7-2-5】用free或delete释放了内存之后,立即将指针设置为NULL,防止产生“野指针”。

7.3指针与数组的对比

7.3.1 修改内容


修改数组和指针的内容

7.3.2 内容复制与比较

不能对数组名进行直接复制与比较。

7.3.3 计算内存容量

数组退化为指针

7.4指针参数是如何传递内存的?

如果函数的参数是一个指针,不要指望用该指针去申请动态内存。

正确的方法可以使用指向指针的指针,或者可以用函数返回值来传递动态内存。不要用return语句返回指向“栈内存”的指针,因为该内存在函数结束时自动消亡。

7.5 free和delete把指针怎么啦?

free/delete掉的指针应该赋NULL值。

7.6 动态内存会被自动释放吗?

(1)指针消亡了,并不表示它所指的内存会被自动释放。

(2)内存被释放了,并不表示指针会消亡或者成了NULL指针。

7.7 杜绝“野指针”

7.8 有了malloc/free为什么还要new/delete ?

对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。

你可能感兴趣的:(第七章 内存管理)