第16章 内存管理
16.1 内存分配方式
内存分配方式有以下3种:
一、从“静态存储区”分配
例如全局变量,static静态变量。
二、从“栈”上分配
例如函数内的局部变量(包括形参)。该类运算效率很高,而且一般不存在失败的危险,但是分配
的内存容量有限(2M?),可能会出现堆栈溢出。
三、从“堆(或称自由存储区)”上分配
亦称动态内存分配。例如malloc,new等申请的内存。该类操作使用灵活,但是较栈上分配开销大。
一般的原则是:如果使用栈存储和静态存储就能满足应用要求,那么就不要使用动态存储(heap)。
2、确保所有的变量在使用前被初始化。
3、内存越界:数组越界。
4、内存泄漏:没有释放或释放不完全。
5、内存释放错误: 多次释放同一块内存。
16.3 指针参数是如何传递内存的?
编译器总是要为函数的每个参数制作临时副本。
16.4 free 和 delete 把指针怎么啦?
释放指针指向的内存后,一定要将指针置NULL,防止产生“野指针”。
16.5 动态内存会被自动释放吗?
永远都不会!
16.7 有了malloc()/free()为什么还要new/delete?
1、malloc()/free()不能自动调用构造函数和析构函数,必须为ADT/UDT类型定义initialize()和destroy()来完成初始化和清除工作。
2、new直接返回目标类型的指针,不需要做显示的类型转换了,而malloc()则返回void*,必须做显示的类型转换后才能使用。
16.8 malloc()/free()的使用要点
1、函数malloc()的原型如下:
void *malloc(size_t size);
2、函数free()的原型如下:
void free(void *memblock);
16.9 new的3种使用方式
1、plain new/delete
void *operator new(std::size_t) throw(std::bad_alloc);
void operator delete(void *) throw();
2、nothrow new/delete
void *operator new(std::size_t, const std::nothrow_t&) throw();
void operator delete(void *) throw();
3、placement new/delete
void *_operator new(size_t, void *);
void _operator delete(void *, void *);
16.10 new/delete的使用要点
1、new/delete 和 new[]/delete[]必须配对使用。
2、多次delete一个不等于NULL的指针p会导致运行时错误。但是delete一个NULL指针式安全的。
16.11 内存耗尽怎么办
一个一般性问题:对于32位及以上的操作系统而言,一般情况下使用malloc() 和 new 几乎不可能导致“内存耗尽”。这是因为32位操作系统支持“虚存”,内存用完了,自动用硬盘空间顶替。因此,对于32位及以上的应用程序,“内存耗尽”的错误处理程序几乎毫无用处。
16.12 用对象模拟指针
1、用对象管理内存
2、泛型指针 auto_ptr
3、智能指针
16.1 内存分配方式
内存分配方式有以下3种:
一、从“静态存储区”分配
例如全局变量,static静态变量。
二、从“栈”上分配
例如函数内的局部变量(包括形参)。该类运算效率很高,而且一般不存在失败的危险,但是分配
的内存容量有限(2M?),可能会出现堆栈溢出。
三、从“堆(或称自由存储区)”上分配
亦称动态内存分配。例如malloc,new等申请的内存。该类操作使用灵活,但是较栈上分配开销大。
一般的原则是:如果使用栈存储和静态存储就能满足应用要求,那么就不要使用动态存储(heap)。
16.2 常见的内存错误及其对策
1、如果指针p是函数的参数,那么在函数的入口处用assert(p != NULL); 进行检查以避免输入非法参数。2、确保所有的变量在使用前被初始化。
3、内存越界:数组越界。
4、内存泄漏:没有释放或释放不完全。
5、内存释放错误: 多次释放同一块内存。
16.3 指针参数是如何传递内存的?
编译器总是要为函数的每个参数制作临时副本。
16.4 free 和 delete 把指针怎么啦?
释放指针指向的内存后,一定要将指针置NULL,防止产生“野指针”。
16.5 动态内存会被自动释放吗?
永远都不会!
16.6 杜绝“野指针”
16.7 有了malloc()/free()为什么还要new/delete?
1、malloc()/free()不能自动调用构造函数和析构函数,必须为ADT/UDT类型定义initialize()和destroy()来完成初始化和清除工作。
2、new直接返回目标类型的指针,不需要做显示的类型转换了,而malloc()则返回void*,必须做显示的类型转换后才能使用。
16.8 malloc()/free()的使用要点
1、函数malloc()的原型如下:
void *malloc(size_t size);
2、函数free()的原型如下:
void free(void *memblock);
16.9 new的3种使用方式
1、plain new/delete
void *operator new(std::size_t) throw(std::bad_alloc);
void operator delete(void *) throw();
2、nothrow new/delete
void *operator new(std::size_t, const std::nothrow_t&) throw();
void operator delete(void *) throw();
3、placement new/delete
void *_operator new(size_t, void *);
void _operator delete(void *, void *);
16.10 new/delete的使用要点
1、new/delete 和 new[]/delete[]必须配对使用。
2、多次delete一个不等于NULL的指针p会导致运行时错误。但是delete一个NULL指针式安全的。
16.11 内存耗尽怎么办
一个一般性问题:对于32位及以上的操作系统而言,一般情况下使用malloc() 和 new 几乎不可能导致“内存耗尽”。这是因为32位操作系统支持“虚存”,内存用完了,自动用硬盘空间顶替。因此,对于32位及以上的应用程序,“内存耗尽”的错误处理程序几乎毫无用处。
16.12 用对象模拟指针
1、用对象管理内存
2、泛型指针 auto_ptr
3、智能指针