C/C++内存管理(1)

C/C++内存管理

http://www.bianceng.cn/Programming/cplus/200705/622.htm

http://www.cnblogs.com/lancidie/archive/2011/08/05/2128318.html

http://www.cnblogs.com/likwo/archive/2010/12/20/1911026.html

参考网上、书上资料及一些自己的理解。。

1、C/C++内存分配方式

内存分配方式有三种:

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

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

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


2、C/C++在内存中的存储结构:

2.1、包括堆、栈、自由存储区、全局/静态存储区常量存储区、代码区(文本区)

堆:

操作系统有一个记录空闲内存地址的链表,当程序用new申请内存空间时,系统会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删 除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样代码 中的delete语句才能正确的释放本内存空间。我们常说的内存泄露,最常见的就是堆泄露(还有资源泄露),它是指程序在运行中出现泄露,如果程序被关闭掉的话,操作系统会帮助释放泄露的内存。

栈:

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

自由存储区:

有malloc等分配的内存空间区,和堆类似,不过由free释放申请的空间

全局/静态存储区:

全局变量和静态变量被分配到同一块内存中,在C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。

常量数据区:用于存放常量,不允许修改

代码区:用于存放C/C++代码块

2.1、堆与栈的区别:

首先举个例子:

void f(){ int *p = new int[100];
	……}

该函数中int *p = new int[100];这条语句就包含堆和栈,首先new分配了一块堆内存,但是指针变量p是存于栈内的,因此栈内存中存放了一个指向一块堆内存的指针p。在程序会先确定在堆中分配内存的大小,然后调用operator new分配内存,然后返回这块内存的首地址,放入栈中。


堆与栈的区别:
a.管理方式:

栈由编译器自动管理,无需手工控制;堆来的释放工作由程序员控制,容易产生内存泄露

b.空间大小:

一般在32位系统下,堆内存可以达4G,几乎是没有什么限制。但对于栈,一般都有一定的空间大小限制

c.碎片产生:

堆由于频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。栈则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出,在他弹出之前,在他上面的后进的栈内容已经被弹出。

d.生长方向:

堆的生长方向是向上的,向着内存地址增加的方向;栈的生长方向是向下的,是向着内存地址减小的方向增长

e.分配方式:

堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。

f.分配效率:

栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多,就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。


例子:

//main.cpp
int a = 0;// 全局初始化区
char *p1; //全局未初始化区
void main()
{
int b; 栈

char s[] = "abc"; 栈 //更正:abc 分配在静态存储区,不是栈上

char *p2; //栈

char *p3 = "123456"; //123456\0在常量区,p3在栈上。

static int c =0; //全局(静态)初始化区

p1 = (char *)malloc(10);

p2 = (char *)malloc(20);

//分配得来得10和20字节的区域就在堆区,但是p1,p2存于栈中

strcpy(p1, "123456"); //123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。
}


你可能感兴趣的:(C/C++内存管理(1))