内存分布
栈
先进先出(First In,Last Out)
队列
先进先出(First In,First Out)
每行代码在内存单元中的地址位置
还有一块常量区,在HEAP和常量区之间
堆heap
动态分配资源
- 从现代的编程语言角度来看,使用堆,或者说使用动态内存分配,是一件很自然不过的事情。
- 动态内存带来了不确定性:内存分配耗时需要多久?失败了怎么办?在实时性要求比较高的场合,如一些嵌入式控制器和电信设备。
- 一般而言,当我们在堆上分配内存时,很多语言会使用new这样的关键字,有些语言则是隐式分配。在C++中new的对应词是delete,是因为C++是可以让程序员完全接管内存的分配释放的。
分配和回收动态内存的原则
程序通常需要牵涉到三个内存管理器的操作:
- 分配一个某个大小的内存块
- 释放一个之前分配的内存块
- 垃圾收拾操作,寻找不再使用的内存块并予以释放。这个回收策略需要实现性能,实时性,额外开销等各方面的平衡有统一和高效的做法。
C++做了1,2两件事;而Java做了1,3两件事。
资源管理方案-RAII
RAII:Resource Acquistion Is Initialization
- 依托栈和析构函数,来对所有的资源-包括堆内存在内进行管理。对RAII的使用,使得C++不需要类似于Java那样的垃圾收集方法,也能有效地对内存进行管理。RAII的存在,也是垃圾收集虽然理论上可以在C++使用,但从来 没有真正流行过的主要原因。
- -RAII有些比较成熟的智能指针代表:如std::auto_ptr和boost:shared_ptr
几种变量的对比
栈和堆中的变量的对比
栈(stack)区 | 堆(heap)区 | |
---|---|---|
作用域 | 函数体内,语句块{}作用域 | 整个程序范围内,由new,malloc开始,delete,free结束 |
编译期间大小确定 | 变量大小范围 | 变量大小范围不确定,需要运行期确定 |
大小范围 | Windows系统默认栈大小是1M,Linux常见默认的栈大小是8M或10M(通过ulimit -s查看;不同linux发行版的命令不保证相同) | 所有系统的堆空间上限是接近内存(虚拟内存)的总大小的(一 部分被OS占用) |
内存分配方式 | 地址由高到低减少 | 地址由低到高增加 |
内容是否可变 | 可变 | 可变 |
全局静态存储区和常量存储区的变量对比
全局静态存储区 | 常量存储区 | |
---|---|---|
存储内容 | 全局变量,静态变量 | 常量 |
编译期间大小是否确定 | 确定 | 确定 |
内容是否可变 | 可变 | 不可变 |
内存释放
内存泄漏
指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
内存泄漏发生原因
- 内存泄漏主要发生在堆内存分配方式中,即“配置了内存后,所有指向该内存的指针都遗失了”。若缺乏语言这样的垃圾回收机制,这样的内存就无法归还系统。
- 因为内存泄漏属于程序运行中的问题,无法通过编译识别,所以只能在程序运行过程中来判别和诊断。