内存中的堆栈

函数调用入栈顺序

在函数调用时,第一个进栈的是主函数中函数调用后的下一条指令的地址,然后是函数的各个参数。再然后是函数中的局部变量。注意静态变量是不入栈的。

Pascal语言中函数参数从左到右入栈的,C语言则从右至左。原因是Pascal语言不支持可变长参数,而C语言支持这种特色。通过栈堆分析可知,自左向右的入栈方式,最前面的参数被压在栈底。除非知道参数个数,否则是无法通过栈指针的相对位移求得最左边的参数。

堆栈溢出

堆栈溢出的产生是由于过多的函数调用,导致调用堆栈无法容纳这些调用的返回地址。堆栈溢出很可能由无限递归(Infinite recursion)产生

#include<stdio.h>
int main()
{
char name[8];
printf("Please type your name:");
gets(name);
printf("Hello.%s!",name);
return 0;
}

编译并且执行,输入ipxodiAAAAAAAAAAAAAAAA,执行完gets(name)之后,堆栈如下:

由于我们输入的name字符串太长,name数组容纳不下,只好向内存顶部继续写‘A‘,如果提前申请动态内存就可以避免堆栈溢出。而

堆栈既可以向下增长(向内存低地址)也可以向上增长, 这依赖于具体的实现。 在我们的例子中, 堆栈是向下增长的。 这是很多计算机的实现方式, 包括Intel, Motorola, SPARC和MIPS处理器。由于堆栈的生长方向与内存的生长方向相反,这些‘A’覆盖了堆栈的 老的元素。‘EBP ret’都被‘A‘覆盖了。在main返回的时候,就会把‘AAAA‘的ASCII码:0x41414141作为返回地址,CPU会试图执行 0x41414141处的指令,结果出现错误。这就是一次堆栈溢出!

堆栈和线程的关系

堆: 是大家共有的空间,分全局堆和局部堆。全局堆就是所有没有分配的空间,局部堆就是用户分配的空间。堆在操作系统对进程初始化的时候分配,运行过程中也可以向系统要额外的堆,但是记得用完了要还给操作系统,要不然就是内存泄漏。
栈:是线程独有的,保存其运行状态和局部自动变量的。栈在线程开始的时候初始化,每个线程的栈互相独立。每个C++对象的数据成员也存在在栈中,每个函数都有自己的栈,栈被用来在函数之间传递参数。操作系统在切换线程的时候会自动的切换栈,就是切换SS/ESP寄存器。栈空间不需要在高级语言里面显式的分配和释放。

时间: 2024-08-26 11:36:07

内存中的堆栈的相关文章

数据结构中的堆栈和内存中的堆栈

内存常用的区域分类:栈区(stack).堆区(heap).全局区(static区).文字常量区.程序代码区. 栈区:由编译器自动分配和释放,遵循”后进先出“的规则.在函数调用时,第一个进栈的是主函数中的下一条指令地址,然后是函数的各个参数(大多数C编译器中,参数从右往左入栈),然后是函数的局部变量.静态变量不入栈. 堆区:一般由程序员分配和释放,若程序员不释放,程序结束时”可能“由操作系统回收.一般在堆的头部用一个字节存放堆的大小.分配方式类似链表. 数据结构中的堆栈: 栈:遵循”后进先出“规则

关于内存中栈和堆的区别(非数据结构中的堆和栈,区别)

本文转载自:http://blog.csdn.net/fenghuayoushi/article/details/6074666 ----------------------------------------------------------------------------------------------------------------------- 下面内容转自:http://www.cnblogs.com/gesenkof99/archive/2009/04/14/14356

C# 深入理解堆栈、堆在内存中的实现

尽管在.NET framework下我们并不需要担心内存管理和垃圾回收(GarbageCollection),但是我们还是应该了解它们,以优化我们的应用程序.同时,还需要具备一些基础的内存管理工作机制的知识,这样能够有助于解释我们日常程序编写中的变量的行为.在本文中我将讲解栈和堆的基本知识,变量类型以及为什么一些变量能够按照它们自己的方式工作. 在.NET framework环境下,当我们的代码执行时,内存中有两个地方用来存储这些代码.假如你不曾了解,那就让我来给你介绍栈(Stack)和堆(He

从内存中堆栈的分配格局解析大小端模式

今天找了一整天的资料,企图弄懂大小端模式的区别,但是弄了很久还是弄不懂.后面尝试从内存中的分配格局来区别,找了大.小端模式下的内存分配格局进行比较,就弄懂了. 先贴出基本知识: 所谓的大端模式Big-endian,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放: 所谓的小端模式Little-endian,是指数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地址中,这种存储

内存中堆栈

一个由c/C++编译的程序占用的内存分为以下几个部分 1.栈区(stack)— 程序运行时由编译器自动分配,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构中的栈.程序结束时由编译器自动释放.2.堆区(heap) — 在内存开辟另一块存储区域.一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 .注意它与数据结构中的堆是两回事,分配方式倒是类似于链表.3.全局区(静态区)(static)—编译器编译时即分配内存.全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态

JS中的堆栈内存

栈内存 俗称作用域 为js代码提供执行环境 基本数据类型值是直接存放在栈内存中的 堆内存 引用数据类型 对象存储的是键值对 函数存储的是代码字符串 在项目中,我们的内存越少性能越好 原文地址:https://www.cnblogs.com/endian11/p/9085686.html

在堆内存中存放十个字符串并输出 堆栈溢出时退出程序

1 # include <stdio.h> 2 # include <stdlib.h> 3 4 # define NUM 10 5 6 int main() 7 { 8 char *str[NUM]; /* 定义一个字符性的指针数组 */ 9 int t; 10 11 /* 为数组中的每个指针分配内存 */ 12 for (t = 0; t<NUM; t++) 13 { 14 if ((str[t] = (char *)malloc(128)) == NULL) 15 {

Dump内存中的Assembly到磁盘

发现ConfuserEx这个开源的.NET加密程序用的人也非常多,尤其是老外.屡屡遇到这东西,很头疼,主要是是没有现成的脱壳程序,需要手动脱壳,虽说难度不大,但它更新的速度挺快,一直在变化,总是给人一种追着才能赶上的感觉,真是不爽.话说来,不知国内是真没有大牛,还是大牛都藏着掖着,那些脱壳的程序都是老外的作品,身在天朝又访问不了GG,只能自己动手了.其实本文的目的是根据内存中的源程序集Rebuild一个新的程序集,之所以不是Dump是因为还要把被混淆过的名称和字符串信息还原,显然Dump不能满足

java中数据在内存中的状态

此文转自csdn,看完瞬间就明白了 首先,我们知道,Java中的数据类型分为两种,基本数据类型和引用数据类型.而基本数据类型,为什么不直接使用他们的包装类呢,例如Integer.Long等等呢?下面是Thinking in Java 中的解释: 有 一系列类需特别对待:可将它们想象成“基本”.“主要”或者“主”(Primitive)类型,进行程序设计时要频繁用到它们.之所以要特别对待,是由于 用new创建对象(特别是小的.简单的变量)并不是非常有效,因为new将对象置于“堆”里.对于这些类型,J