5.1.堆、栈、数据区、bss、代码段
2016-07-16 19:45
218 查看
一个程序的运行是需要内存的,那么我们平常写的程序的内存都是怎么分配的呢?都是在一起存放?还是分开?按照什么规律呢?
预备知识:
(1)首先我们要知道,内存是真实存在的,内存是一个物理器件。它时由操作系统管理的,我们平常只要使用它就行了,为了方便管理。操作系统提供了很多种机制来管理内存,每一种机制都有其特点。
(2)三种内存来源:栈(stack)、堆(heap)、数据区(data)
(3)我们获取内存的来源就是其中一种,(C语言程序中)
1.什么是栈?
1.1.栈的特点
(1)使用时自动分配,用完自动释放。
总结:a和b都是局部变量,都是栈内存,自动分配和释放。
(2)栈内存不干净,反复使用。使用完后不会清零,这就是为什么每次分配局部变量若不初始化就是随机值的原因。
(4)临时性:函数不能返回栈变量的指针。局部变量的地址是不能返回的。在一个函数内部分配的局部变量在函数结束时,其内存就已经不存在了。返回其地址是很危险的。
分析:
(1)test函数能不能返回p的值?
(2)能不能通过 *w = 20?
(3)数组越界问题 (栈溢出)
给arr数组分配了5个地址空间,非要去访问第11个空间,不是你家,你非要进,绝对会打你的。
2.什么是堆?
(1)操作系统堆管理器管理。堆管理器是操作系统的一个模块
(2)大块内存,分配自如。按需分配。
(3)堆内存手动分配&释放,malloc,free
(4)脏内存。堆内存也是反复使用的,而且使用者用完之前不会清零,因此也是脏的。堆管理器不会去清零堆内存,下一个使用的变量才去清零。
(5)堆内存。从分配到释放一直属于我这个进程,之前或者之后都不可以再访问。
//堆内存的使用范例
3.数据区
(1)数据段:(也被称作数据区、静态数据区、静态区)程序运行所需要的数据存放在这,比如函数执行过程中调用的一些变量(全局变量),产生的一些数据。注意:全局变量才算是程序的数据,局部变量算是函数的数据,局部变量不是程序的数据。 局部变量属于栈管理,在栈分配。
(2)bss段
bss段:(也叫ZI段,zero initial 段,bss段的特点就是被初始化为0,bss段本质上也是数据段,bss段就是被初始化为0的数据段)
总结:(1)全局变量初始化为非0,存放在数据段。
static修饰的局部变量存放到数据段
(2)全局变量 未初始化 或 初始化为0,存放在bss段
(3)bss段是数据区的一部分
4.代码段
就是存放代码的地方,需要注意的是像char *p=”linux”;这样的也会被分配的代码段,代码段的东西时不可以被修改的。
接下来我们看一个程序,具体分析,每一个变量存放在哪里
总结:
(1)程序经过编译后,分成不同的段,程序就是由好多个段组成的。数据段,代码段,bss段。
(2)全局变量才属于程序的数据,局部变量属于函数的数据。
(3)有些特殊数据会放在代码段,像字符串。
预备知识:
(1)首先我们要知道,内存是真实存在的,内存是一个物理器件。它时由操作系统管理的,我们平常只要使用它就行了,为了方便管理。操作系统提供了很多种机制来管理内存,每一种机制都有其特点。
(2)三种内存来源:栈(stack)、堆(heap)、数据区(data)
(3)我们获取内存的来源就是其中一种,(C语言程序中)
1.什么是栈?
1.1.栈的特点
(1)使用时自动分配,用完自动释放。
#include<stdio.h> main() { int a = 1; int b = 2; }
总结:a和b都是局部变量,都是栈内存,自动分配和释放。
(2)栈内存不干净,反复使用。使用完后不会清零,这就是为什么每次分配局部变量若不初始化就是随机值的原因。
int a ; printf("a = %d\n",a); //绝对是随机值
(4)临时性:函数不能返回栈变量的指针。局部变量的地址是不能返回的。在一个函数内部分配的局部变量在函数结束时,其内存就已经不存在了。返回其地址是很危险的。
#include<stdio.h> int * test(); main() { int * w; //局部变量,栈上分配 w = test(); *w = 20; } int* test() { int a = 10; /局部变量,栈上分配 局部变量,作用域为test函数,生命周期为test函数从执行到执行完毕 int *p = &a; return p; }
分析:
(1)test函数能不能返回p的值?
test函数中的a和p都是局部变量,作用域为test函数,生命周期为test函数从执行到执行完毕,当test函数执行完后,为a和p分配的栈上的内存已经释放了。也就是说,原来分配的地址已经不能在被a和p使用了。这里可以返回p的值,只是没有意义了,而是很危险的行为。
(2)能不能通过 *w = 20?
能访问,但可能会出错,原a的内存已经被释放,原来的地址已经不再属于a,这时候就会使程序崩溃。访问了不属于它的地址。
(3)数组越界问题 (栈溢出)
main() { int arr[5]; //局部变量,栈上分配 arr[10] = 100; }
给arr数组分配了5个地址空间,非要去访问第11个空间,不是你家,你非要进,绝对会打你的。
2.什么是堆?
(1)操作系统堆管理器管理。堆管理器是操作系统的一个模块
(2)大块内存,分配自如。按需分配。
(3)堆内存手动分配&释放,malloc,free
(4)脏内存。堆内存也是反复使用的,而且使用者用完之前不会清零,因此也是脏的。堆管理器不会去清零堆内存,下一个使用的变量才去清零。
(5)堆内存。从分配到释放一直属于我这个进程,之前或者之后都不可以再访问。
//堆内存的使用范例
main() { int*p=(int *)malloc(1000*sizeof(int)); } //使用malloc()分配的内存是在堆上分配的 //这里的p仍旧是栈上分配,p是一个指针。该指针指向的内存是堆内存。(4000个字节的首四个字节)
3.数据区
(1)数据段:(也被称作数据区、静态数据区、静态区)程序运行所需要的数据存放在这,比如函数执行过程中调用的一些变量(全局变量),产生的一些数据。注意:全局变量才算是程序的数据,局部变量算是函数的数据,局部变量不是程序的数据。 局部变量属于栈管理,在栈分配。
(2)bss段
bss段:(也叫ZI段,zero initial 段,bss段的特点就是被初始化为0,bss段本质上也是数据段,bss段就是被初始化为0的数据段)
总结:(1)全局变量初始化为非0,存放在数据段。
static修饰的局部变量存放到数据段
(2)全局变量 未初始化 或 初始化为0,存放在bss段
(3)bss段是数据区的一部分
4.代码段
就是存放代码的地方,需要注意的是像char *p=”linux”;这样的也会被分配的代码段,代码段的东西时不可以被修改的。
接下来我们看一个程序,具体分析,每一个变量存放在哪里
#include<stdio.h> int test1 = 250 //全局变量,数据区 int test2 = 0 //初始化为0的全局变量,数据区的bss段 int test3 //未初始化全局变量,数据区的bss段 char * display();//代码段 void main() { int ok1 = 1; /* 局部变量 int ok2 = 0; 栈上分配 int ok3; */ int * pre; //局部变量指针,栈上分配 pre = display(); } int * display(); { char * word = "he is goudan"; //代码段 int * re = (int*)malloc(100*sizeof(int)); //re指针在栈分配 //re指针指向的是内存在堆上分配 //当display()函数执行完毕后,re指针本身地址被释放, //re所指向的堆内存依旧存在(若未保留该指针则内存泄漏) return re; }
总结:
(1)程序经过编译后,分成不同的段,程序就是由好多个段组成的。数据段,代码段,bss段。
(2)全局变量才属于程序的数据,局部变量属于函数的数据。
(3)有些特殊数据会放在代码段,像字符串。
相关文章推荐
- Ruby基础知识之方法、代码段
- C++基于栈实现铁轨问题
- 浅析C语言中堆和栈的区别
- C语言栈的表示与实现实例详解
- C语言实现颠倒栈的方法
- 算法系列15天速成 第十天 栈
- PHP常用的小程序代码段
- Node.js实用代码段之正确拼接Buffer
- 一看就懂:图解C#中的值类型、引用类型、栈、堆、ref、out
- Array栈方法和队列方法的特点说明
- 50个比较实用jQuery代码段
- java数据结构之java实现栈
- 浅析栈区和堆区内存分配的区别
- 用Java代码实现栈数据结构的基本方法归纳
- 用PHP解决的一个栈的面试题
- Node.js实用代码段之获取Buffer对象字节长度
- 浅谈C#中堆和栈的区别(附上图解)
- C#使用Object类实现栈的方法详解
- JavaScript数据结构与算法之栈详解
- Android开发常用经典代码段集锦