关于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都采取了各种办法随机化栈地址对栈进行保护。
关于C、内存、栈的一些杂谈的更多相关文章
- js的基础(平民理解的执行上下文/调用堆栈/内存栈/值类型/引用类型)
与以前的切图比较,现在的前端开发对js的要求似乎越来越高,在开发中,我们不仅仅是要知道如何运用现有的框架(react/vue/ng), 而且我们对一些基础的知识的依赖越来越大. 现在我们就用平民的方法 ...
- 栈 堆 stack heap 堆内存 栈内存 内存分配中的堆和栈 掌握堆内存的权柄就是返回的指针 栈是面向线程的而堆是面向进程的。 new/delete and malloc/ free 指针与内存模型
小结: 1.栈内存 为什么快? Due to this nature, the process of storing and retrieving data from the stack is ver ...
- (二)程序中的内存&&栈
一.程序运行为什么需要内存?基本概念? 内存是程序运行的立足之地,程序需要用内存来存储一些变量. 内存管理最终是由操作系统完成的,内存在本质上是一个硬件器件,由硬件系统提供:内存由操作系统统一管理,为 ...
- 浅谈c语言程序为什么需要内存 栈又是什么?
.关于内存(程序的执行需要内存的支持) ()内存本身在物理上是硬件器件,由操作系统提供 ()内存的管理最终由操作系统统一管理.为了能过便捷的管理内存(酒店管理房间 是不是分很多不同的类型和待遇呢),同 ...
- 内存栈与堆的区别C#
C# 堆与栈 理解堆与栈对于理解.NET中的内存管理.垃圾回收.错误和异常.调试与日志有很大的帮助.垃圾回收的机制使程序员从复杂的内存管理中解脱出来,虽然绝大多数的C#程序并不需要程序员手动管理内存, ...
- 【转】jvm 堆内存 栈内存 大小设置
原文地址:http://blog.csdn.net/qh_java/article/details/46608395 4种方式配置不同作用域的jvm的堆栈内存! 1.Eclise 中设置jvm内存: ...
- C++ 动态内存 栈堆
C++ 动态内存_w3cschool https://www.w3cschool.cn/cpp/cpp-dynamic-memory.html
- jvm 堆内存 栈内存 大小设置
4种方式配置不同作用域的jvm的堆栈内存. 1.Eclise 中设置jvm内存: 改动eclipse的配置文件,对全部project都起作用 改动eclipse ...
- java堆内存与栈内存
java的内存分为两种,堆内存与栈内存: 堆内存用来存放数组和new的对象,比如一个文件,字节流是存放在堆中,栈内存为这个文件开辟一个索引,也就是这个文件的地址,并且保存在栈中.对象由GC处理释放内存 ...
随机推荐
- MotionEvent的getX(),getY()与getRawX(),getRawY()区别
在Android的View中getX getRawX获取的坐标是不一样的,只是相对比照的对象不一样而已. 1.在View中: getX()是表示Widget相对于自身左上角的x坐标,而getRawX ...
- struts 上传文件 Dynavalidatorform 实例
一.相关jar包 一个空struts工程的jar包: 另上传文件的两个jar包: 二.页面 1.上传页面upload.jsp <%@ page language="jav ...
- PowerShell 脚本域策略管理
大中型企业中,会设置许多组策略进行日常运维管理 ,毕然里面也存在许多废弃的策略,需要我们定期清理我们的组策略信息.通常我们导出HTML报告方式来帮助我们分析组策略信息: #1 首先需要加载GroupP ...
- JSON:使用json_encode函数解析结果为Null
1.首先,数据库中的json数据是这样的 2.仓鼠使用json_encode()函数进行解析json数据时,显示了一个NULL: 3.这时候,我们需要使用,表示在解析json之前,该json是有语法错 ...
- 如何在 ubuntu linux 一行中执行多条指令
cd /my_folder rm *.jar svn co path to repo mvn compile package install 使用&& 运算符连接指令 cd /my_f ...
- SQL的注入式攻击方式和避免方法
SQL 注入是一种攻击方式,在这种攻击方式中,恶意代码被插入到字符串中,然后将该字符串传递到 SQL Server 的实例以进行分析和执行.任何构成 SQL 语句的过程都应进行注入漏洞检查,因为 SQ ...
- softmax sigmoid
softmax和sigmoid实际上都是属于logistic regression,sigmoid是二分类的lr,拟合Bernoulli distribution(二项分布):0softmax是多分类 ...
- C语言函数申明关键字inline
内联inline是给编译器的优化提示,如果一个函数被编译成inline的话,那么就会把函数里面的代码直接插入到调用这个函数的地方,而不是用调用函数的形式.如果函数体代码很短的话,这样会比较有效率,因为 ...
- scrapy Pipeline 练习
class WeatherPipeline(object): def process_item(self, item, spider): print(item) return item #插入到red ...
- C# unchecked运算符
一.C# unchecked运算符 unchecked运算符用于取消整型算术运算和转换的溢出检查. 二.提示 默认情况下,都是unchecked选项.因此,只有在需要把几个未检查的代码行放在一个明确标 ...