《内存分区堆区栈区数据段代码段》由会员分享,可在线阅读,更多相关《内存分区堆区栈区数据段代码段(6页珍藏版)》请在金锄头文库上搜索。
1、内存分区 : 堆区 栈区数据段代码段1.函数代码存放在代码段。声明的类如果从未使用,则在编译时,会优化掉,其成员函数不占代码段空间。全局变量或静态变量,放在数据段,局部变量放在栈中,用 new产生的对象放在堆中,内存分为 4 段,栈区,堆区,代码区,全局变量区BSS段:BSS 段(bss segment )通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文 Block Started by Symbol的简称。 BSS 段属于静态内存分配。2.代码段、数据段、栈是CPU 级别的逻辑概念,堆是语言级别的逻辑概念3.还有一个常量区,其中的内容不许修改。常见的 char *p =
2、“hello“; 这里面的 “hello“就保存在常量区4.如 1 楼所说,把代码段、数据段,栈,堆这些并列在一起不太合适代码段、数据段、堆栈段,这是一个概念堆、栈、全局区、常量区,这是另一个概念5.STACK(栈)临时局部HEAP(堆)动态RW(读写)全局RO(只读)代码Char* s= ”Hello,World”; S中“H”存放在内存 RO 中且不能修改。6.CPU 寄存器: CPU 寄存器,其实就是来控制代码段和数据段的指令及数据读取的地方,当然, CPU 也有自己存放数据的地方,那就是通用寄存器里的数据寄存器,通常是 EDX 寄存器, C 语言里有个 register,就是把数据放在
3、这个寄存器里,这样读取数据就相当的快了,因为不用去内存找, 就省去了寻址和传送数据的时间开销。他还有一些寄存器是用来指示当前代码段的位置、数据段的位置、堆栈段的位置等等 (注意这里存放的只是相应的代码或数据在内存中的地址,并不是实际的值, 然后根据这个地址, 通过地址总线和数据总线, 去内存中获取相应的值 ),不然在执行代码的时候,指令和数据从哪取呢?呵呵。 。他里面还有标志寄存器,用来标识一些状态位,比如标识算术溢出呀等等。 。 。 。内存分段(笔记)在冯诺依曼的体系结构中必须有:代码段,堆栈段,数据段因为冯氏结构,本质就是取址,执行的过程编译器和系统在为变量分配是从高地址开始分配的. 全局
4、变量和函数参数在内存中的存储是由低地值到高地址的. 函数参数为什么会放到堆区呢?这是因为我们的函数是在程序运行中进行动态的调用的. 在函数的编译阶段根本无法确定他会调用几次,会需要多少内存. 即使可以确定那时候就为变量分配好内存着实也是一种浪费。所以编译器为函数参数选择动态的分配.即在每次调用函数时才为它动态的进行分配空间 . # 内存分为 4 段,栈区,堆区,代码区,全局变量区BSS段:BSS 段(bss segment )通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文 Block Started by Symbol的简称。 BSS 段属于静态内存分配。数据段:数据段(
5、 data segment )通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。代码段:代码段( code segment/text segment )通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许修改程序。在代码段中, 也有可能包含一些只读的常数变量,例如字符串常量等。 代码段是存放了程序代码的数据,假如机器中有数个进程运行相同的一个程序,那么它们就可以使用同一个代码段。堆(heap ) :堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩
6、减。当进程调用malloc 等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张) ;当利用 free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)栈(stack):栈又称堆栈,是用户存放程序临时创建的局部变量,也就是说我们函数括弧 “ ”中定义的变量(但不包括static 声明的变量, static意味着在数据段中存放变量) 。除此以外, 在函数被调用时, 其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。(1)内存分
7、段和内存分页一样都是一种内存管理技术,分段:权限保护 ,分页:虚拟内存. (2)分段后 ,程序员可以定义自己的段,各段有独立的地址空间,象进程的地址空间互相独立一样 . (3)同一个类的实例分配在一个段中,只有该类的方法可以访问,如果其他类的方法去访问 ,会因为段保护而出错 .可以从硬件上实现类的数据保护和隐藏# 分段好处:cpu 中的段寄存器 -段址( base )和偏移值的上限( limit ) 。段址:有效地址中,如果有效地址大于limit ,便会引发异常。这样就可以限制程序不能范围当前段外的数据,不能访问其他程序的数据。面向对象的好处 :对象就是一块连续的内存中的数据寄存器是特殊形式的
8、内存,嵌入到处理器内部。每个进程需要访问内存中属于自身的区域,因此,可将内存划分成小的段,按需分发给进程。寄存器用来存储和跟踪进程当前维护的段。偏移寄存器(Offset Registers)用来跟踪关键的数据放在段中的位置。在进程被载入内存中时,基本上被分裂成许多小的节(section) 。我们比较关注的是 6 个主要的节:(1) .text 节.text 节基本上相当于二进制可执行文件的.text 部分,它包含了完成程序任务的机器指令。该节标记为只读,如果发生写操作,会造成segmentation fault。在进程最初被加载到内存中开始,该节的大小就被固定。(2).data 节.data节
9、用来存储初始化过的变量,如:int a =0 ; 该节的大小在运行时固定的。(3).bss 节栈下节( below stack section ,即.bss )用来存储为初始化的变量,如:int a; 该节的大小在运行时固定的。(4) 堆节堆节(heap section )用来存储动态分配的变量,位置从内存的低地址向高地址增长。内存的分配和释放通过malloc() 和 free() 函数控制。(5) 栈节栈节(stack section )用来跟踪函数调用(可能是递归的) ,在大多数系统上从内存的高地址向低地址增长。同时,栈这种增长方式,导致了缓冲区溢出的可能性。(6)环境 /参数节环境/参数
10、节( environment/arguments section)用来存储系统环境变量的一份复制文件,进程在运行时可能需要。例如,运行中的进程,可以通过环境变量来访问路径、shell 名称、主机名等信息。该节是可写的,因此在格式串(format string)和缓冲区溢出( buffer overflow )攻击中都可以使用该节。另外,命令行参数也保持在该区域中。# 以 win32 程序为例。程序执行时,操作系统将exe文件映射入内存。 exe文件格式为头数据和各段数据组成。头数据说明了 exe 文件的属性和执行环境,段数据又分为数据段,代码段,资源段等,段的多少和位置由头数据说明。也就是说,
11、不仅仅只是代码段和数据段。 这些段由不同的编译环境和编译参数控制,由编译器自动生成exe的段和文件格式。当操作系统执行 exe时,会动态建立堆栈段,它是动态的,并且属于操作系统执行环境。也就是说,程序在内存的映射一个为exe 文件映射,包括数据段、代码段等它是不变的。另一个为堆栈段,它是随程序运行动态改变的。1、编译器把源代码转化成分立的目标代码(.o 或者.obj)文件,这些文件中的代码已经是可执行的机器码或者是中间代码。但是其中变量等事物的地址只是一些符号。2、接下来是通过链接器处理这些目标代码,主要目的就是把分立的目标代码连接成一份完整的可执行代码,并将其中的地址符号换成相对地址。如果这时候产生错误, 我们就可以得到一份地址符号列表,而不是变量列表。3、执行程序的时候操作系统分配足够的内存空间,建立好系统支撑结构后把二进制可执行代码读入内存中。在读入过程中内存首址就成了程序的“ 绝对地址 ” (实际上还是相对地址, 不过是操作系统里的相对地址了) 。于是绝对地址 +相对地址(就是偏移量)就得到了变量的地址。因此, CS 的值是由系统填入的,而其它S 寄存器的值则是根据程序代码中附加的信息计算后得到的。版权声明:本文为博主原创文章,未经博主允许不得转载。