在日常工作中,我们时常会说到堆栈。虽然堆栈总是一起说起,但是实际上这是两个不同的概念。
首先简单来说呢,堆和栈都在RAM中,一般被分配的区域也是相同的一块区域,只是堆从下往上存储,栈从上往下存储。此时应该注意堆和栈在不断增长的过程可能会互踩内存,就会出现意外error,所以在使用时应该注意用完堆栈及时释放或者划分的内存大一些。另外呢,栈是编译器自动分配和释放的,比如函数的参数、局部变量的值等。堆一般是程序员分配和释放的,分配方式类似于数据结构中的链表。
下面举例具体说明:
如上图的示例程序所示,全局变量和常量属于静态区(Static),由编译器事先分配好,生命周期贯穿整个程序;函数的参数值,局部变量的值属于栈(Stack),由编译器自动分配和释放;程序员用malloc函数动态请求分配的内存空间属于堆(Heap)。值得注意的是,如果在动态分配的内存用完之后忘记使用free函数释放内存,则会导致内存泄漏,并且当堆和栈无止境的增长到互相覆盖对方区域时则会出现很多无法预料的问题。程序可能运行着就跑飞了。
.bss .data .text这三个段应该属于static段。
BSS段(bss segment): 通常指用来存放程序中未初始化的全局变量的一块内存区域。BSS段属于静态内存分配。
数据段(data segment): 通常指用来存放程序中已初始化的全局变量的一块内存区域,也属于静态内存分配。
代码段(code segment/text segment): 通常指用来存放程序执行代码的一块内存区域,这部分区域的大小在程序运行前就已经确定,并且内存区域通常会被设置为只读权限,当然在某些架构中也允许代码段可写,即允许修改程序,在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。
堆(heap): 用于存放进程运行中被动态分配的内存段,大小并不固定,可动态扩张或缩减,当进程调用malloc等函数分配时,新分配的内存就被动态的添加到堆上,当调用free等函数释放内存时,被释放的内存就会从堆中被剔除(堆被缩减)。
栈(stack): 又称为堆栈,是用户存放程序临时创建的局部变量,当函数被调用时,其参数(本质是寄存器,eax,ebx)会被压入堆栈中,待调用函数执行完毕后,被压入堆栈的参数就会被pop出来。另外函数体中定义的临时变量会被存放于堆栈中,堆栈是由操作系统分配的,内存的申请与回收都是由os决定的。
注意:static变量,又称为静态变量,这种变量存储于数据段上,无论该变量是全局变量还是局部变量,静态全局变量的作用域仅限于该文件,而静态局部变量的作用域则仅在其定义所在的复合语句内。只要static声明的变量,都会存放于数据段中,如果没有赋值,则默认为0。