关于C、内存、栈的一些杂谈

c的程序要手动管理内存的,所有的数据(结构)都可以分为两种存储方式,连续存储,顾名思义申请一片连续的内存以供使用(数组、结构体、共用体、栈、队列);非连续存储,顾名思义断断续续的的存储,那有一点这有一点(链表,链表实现的树)。

对齐填充,这个东西很有意思,看似无用其实很关键,比如有个结构体:

struct xo { int i;char j,int k};

结构体是连续存储的,我们设这个结构体起始地址为0x0,那么 i 的地址 就是 0x0 、j就是0x4、k就是0x5,可是呢OS(操作系统)不允许这样做,为什么呢?因为不好访问,windows就规定 k个字节数据的地址必须是k的整数倍,同理其他的OS也有类似规定,那么xo本来只占9字节,对齐填充之后就变成了12字节,也就是把j的1字节后面硬填了三个空白字节。这种对齐要求,在OS中比比皆是(尤其是在申请内存的时候,往往都是2、4、8的倍数)。

栈帧结构,函数是通过栈来调用的,以栈帧为单位,当前函数就是栈顶帧,栈帧格式大概如下:

本地、临时变量表           
构造参数表
。。。。。一些东西
返回地址                   +4(偏移地址)
保存的%ebp             (这里是栈顶)

栈是自高地址向低地址的,通过栈顶指针+偏移地址访问栈帧里的东西,栈帧的大小在调用函数(过程)的时候固定了(同样需要对齐),这也就可以解释为什么数组越界的后果非常严重了,函数中定义的数组一但越界,也就是说栈帧的大小不够了,装不下他了,那么他就会向上覆盖变量表、甚至上一帧的返回地址等等,使得程序不知所措甚至崩溃。

同样栈帧的地址固定极容易被攻击,导致缓冲区泄露(想一想为什么呢?)   当然现在的OS都采取了各种办法随机化栈地址对栈进行保护。

时间: 2024-11-07 07:01:15

关于C、内存、栈的一些杂谈的相关文章

(二)程序中的内存&&栈

一.程序运行为什么需要内存?基本概念? 内存是程序运行的立足之地,程序需要用内存来存储一些变量. 内存管理最终是由操作系统完成的,内存在本质上是一个硬件器件,由硬件系统提供:内存由操作系统统一管理,为了管理内存方便,操作系统提供了很多机制来让我们应用程序使用内存.这些机制彼此不同,各有各的特点,我们程序根据自己的实际情况来分配内存(暂时获得内存的使用权),使用内存,释放内存(向操作系统归还内存使用权限).在C语言中获得内从的方法为栈.堆.数据区 二.栈 在C语言中,局部变量是存在于栈中的,栈是一

浅谈c语言程序为什么需要内存 栈又是什么?

1 1.关于内存(程序的执行需要内存的支持) 2 (1)内存本身在物理上是硬件器件,由操作系统提供 3 (2)内存的管理最终由操作系统统一管理.为了能过便捷的管理内存(酒店管理房间 是不是分很多不同的类型和待遇呢),同样操作系统提供了多种的机制来让了多种机制来让我们应用程序使用内存.这些机制彼此不同,各自有各自的特点,我们程序根据自己的实际情况来选择某种方式获取内存(在操作系统处登记这块内存的临时使用权限).使用内存.释放内存(向操作系统归还这块内存的使用权限).也就是在进入酒店拿到钥匙或者卡,

java复习第三天-局部变量的初始化和内存中的机制-this调用内存栈

定义了局部变量以后系统并不会为分配内存空间,显示初始化以后系统才会为其分配内存空间,保存在其所在栈的内存中. this调用另一个重载的构造器只能在构造器中使用,而且必须作为构造体的第一条 执行语句.

java中内存堆,内存栈,常量池三者的关系

1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. 2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中.) 3. 堆:存放所有new出来的对象. 4. 静态域:存放静态成员(static定义的) 5. 常量池:存放字符串常量和基本类型常量(public static final). 6. 非RAM存储:硬盘等永久存储空间 这里我们主要关心栈,堆和常量池,对于栈和常量池中的对象

堆内存 栈内存 虚拟内存 动态内存管理

从编译器角度来看内存分三种情况: 1 系统初始化时都已经确定好.不会再变动的内存区域,一般指的是全局变量.静态变量数组等. 2 栈上内存:一般指的是函数内部的局部变量等,函数调用时分配内存,调用结束后系统自动释放不用自己考虑回收,效率高.有时候栈需要自己设定,设定不当可造成栈溢出. 3 堆上内存:即用动态分配函数分配的内存属于堆上内存,适合那些有MMU(内存管理).开始不确定需要申请多大内存的场合.注意:利用动态分配内存函数,使用完毕要及时释放内存和将指针清0,否则容易产生野指针和内存泄露.因为

内存栈与堆的区别C#

C# 堆与栈 理解堆与栈对于理解.NET中的内存管理.垃圾回收.错误和异常.调试与日志有很大的帮助.垃圾回收的机制使程序员从复杂的内存管理中解脱出来,虽然绝大多数的C#程序并不需要程序员手动管理内存,但这并不代表程序员就无需了解分配的对象是如何被回收的,在一些特殊的场合仍需要程序员手动进行内存管理. 在32位的处理器上,每个进程的虚拟内存为4GB,.NET会在这4GB的内存块中开辟出3块内存,分别作为栈.托管堆.和非托管堆 堆(heap): 堆是从下往上分配,所以已用的空间在自由空间下面,C#中

jvm 堆内存 栈内存 大小设置

  4种方式配置不同作用域的jvm的堆栈内存! 1.Eclise 中设置jvm内存: 修改eclipse的配置文件,对所有工程都起作用 修改eclipse根目录下的eclipse.ini文件 -vmargs  //虚拟机设置 -Xms40m //初始内存 -Xmx256m //最大内存 -Xmn16m //最小内存 -XX:PermSize=128M //非堆内存 -XX:MaxPermSize=256M  2.Eclise 中设置jvm内存:jres VM Arguments参数的设置,对所有

【转】jvm 堆内存 栈内存 大小设置

原文地址:http://blog.csdn.net/qh_java/article/details/46608395 4种方式配置不同作用域的jvm的堆栈内存! 1.Eclise 中设置jvm内存: 修改eclipse的配置文件,对所有工程都起作用 修改eclipse根目录下的eclipse.ini文件 -vmargs  //虚拟机设置 -Xms40m //初始内存 -Xmx256m //最大内存 -Xmn16m //最小内存 -XX:PermSize=128M //非堆内存 -XX:MaxPe

java堆内存,栈内存

栈内存 栈内存中储存基本类型的变量(int a =3:)和引用类型的变量(Car  car).当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另作他用. 堆内存 堆内存中存放由new创建的对象和数组,如new Auto;new int [];引用变量是普通变量,定义时在栈中分配内存,引用变量在程序运行到作用域外释放.而数组&对象本身在堆中分配,即使程序运行到使用new产生数组和对象的语句