今天在Linux上调试程序程序的时候发现有时候程序会莫名其妙的hang住,于是就想能不能找到当时程序有那些线程,都在做什么。找了一下linux命令,还真可以满足我的需求。下面看一个小例子。...args=()) t1.start() t2.start() time.sleep(12345) 然后运行这个程序 $ python test.py 先使用 “pstree -apl ” 查看进程结构...$ pstree -apl 26855 python,26855 test.py |-{python},26858 |-{python},26859 然后使用 “ps -Lf ” 查看线程信息...in __libc_start_main () from /lib64/libc.so.6 #20 0x000000000040071e in _start () 这里多说一句,如果要看java程序的栈信息...,可以使用 "kill -3 " 来查看,比如: $ nohub java Test > test.out & $ kill -3
每个方法被执行的时候,java虚拟机都会同步创建一个栈帧,栈的基本单位为栈帧,每个线程都有自已的栈,每个执行方法对应一个栈帧,也叫当前栈帧。...每一个栈帧都包括了局部变量表,操作数栈,动态连接,方法返回地址和一些额外的附加信息。 栈的特点就是后进先出,类似于坐电梯,后面进来的先出去。...特点: 局部变量的生命周期与栈帧一致:随着方法栈的销毁,局部变量随着销毁。...注: 操作数栈最大深度不会超过:max_stacks数据项中设定的最大值 byte、short和char类型在入栈前会被转成int类型; 虽然两个不同帧是相互独立的但是,为了节约一些空间,对栈进行了优化...注意:若调用方法返回的时候带了返回值,其返回会被压入当前栈帧的操作数中,并更新PC寄存器中一条需要执行的字节码指令。
栈帧是用于支持虚拟机进行方法调用和方法执行背后的数据结构。栈帧存储了方法的局部变量表、操作数栈、动态连接和方法返回地址信息。...操作数栈 操作数栈,也称操作栈,是一个后入先出栈。...当一个方法刚刚开始执行的时候, 该方法的操作数栈也是空的, 在方法的执行过程中, 会有各种字节码指令往操作数栈中写入和提取内容, 也就是出栈与入栈操作。...动态连接 每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用, 持有引用是为了支持方法调用过程中的动态连接(Dynamic Linking)。
今天在Linux上调试程序程序的时候发现有时候程序会莫名其妙的hang住,于是就想能不能找到当时程序有那些线程,都在做什么。找了一下linux命令,还真可以满足我的需求。下面看一个小例子。...test2, args=()) t1.start() t2.start() time.sleep(12345) 然后运行这个程序 $ python test.py 先使用 “pstree -apl ” 查看进程结构...$ pstree -apl 26855 python,26855 test.py |-{python},26858 |-{python},26859 然后使用 “ps -Lf ” 查看线程信息 $...in __libc_start_main () from /lib64/libc.so.6 #20 0x000000000040071e in _start () 这里多说一句,如果要看java程序的栈信息...,可以使用 “kill -3 ” 来查看,比如: $ nohub java Test > test.out & $ kill -3 以上就是本文的全部内容,希望对大家的学习有所帮助。
提示:以下是本篇文章正文内容,下面案例可供参考 一、函数栈帧 1.1函数栈帧的概念 函数栈帧是指在函数被调用时,系统为该函数在栈(Stack)区域中开辟的一段存储空间。...1.2函数栈帧的作用 函数栈帧是程序执行过程中用来进行内存管理的必备工具。当函数被调用时,系统为该函数分配栈帧空间,将函数的返回地址、帧指针、局部变量、参数等信息保存在栈帧中。...2.1减少栈帧的大小 由于函数栈帧的大小直接影响程序内存的使用效率,因此我们可以通过一些优化手段减少栈帧的大小,从而提升程序的性能。...减少栈帧的深度 由于栈帧的深度直接影响栈的大小和内存的使用效率,因此我们可以通过减少栈帧的深度来提升程序的性能。...3.4调用栈打印和跟踪: 调试器通常提供了打印调用栈和抓取栈帧的功能,可以在程序出现问题时帮助我们定位问题。借助调试器,我们可以查看函数的调用顺序、每个函数的参数和局部变量,以及返回地址等信息。
单个函数调用操作所使用的栈部分被称为栈帧(stack frame)结构,其一般结构如下图所示。栈帧结构的两端由两个指针来指定。...在函数执行过程中,栈指针esp会随着数据的入栈和出栈而移动,因此函数中对大部分数据的访问都基于帧指针%ebp进行。?对于函数A调用函数B的情况,传递给B的参数包含在A的栈帧中。...当A调用B时,函数A的返回地址(调用返回后继续执行的指令地址)被压入栈中,栈中该位置也明确指明了A栈帧的结束处。而B的栈帧则从随后的栈部分开始,即图中保存帧指针(ebp)的地方开始。...这两个函数的栈帧结构如图3-5所示。可以看出,函数swap()从调用者main()的栈帧中获取其参数。图中的位置信息相对于寄存器ebp中的帧指针。栈帧左边的数字指出了相对于帧指针的地址偏移值。...前两行用来设置保存调用者的帧指针和设置本函数的栈帧指针,第5行通过把栈指针esp下移4字节为局部变量c分配空间。6~15行是swap函数的主体部分。
一般来讲,栈帧之间都是独立的,但是大多虚拟机都会做优化,使局部变量表和操作数栈之间有重叠,以达到共用的目的,这样能节省额外的参数复制等工作,重叠过程类似下图。...动态连接每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,Class 文件的常量池中存有大量的符号引用。字节码中的方法调用指令就以常量池中方法的符号引用为参数。...方法返回时可能会在栈帧中保存一些信息,用来恢复上层方法的执行状态。一般方法正常退出的时候,调用者的pc计数器的值可以作为返回地址,帧栈中很有可能会保存这个计数器的值作为返回地址。...方法退出的过程就是栈帧在虚拟机栈上的出栈过程,因此退出时的操作可能有:恢复上层方法的局部变量表和操作数栈,把返回值压入调用者的操作数栈每条整pc计数器的值指向调用该方法的后一条指令。...如果异常退出的话,返回地址是通过异常表来确定,栈帧中一般不会保存这部分信息。这两个出口的区别就在于,异常完成出口退出是不会给上一层调用者产生任何返回值的。
,至此main函数的栈帧保护工作完成,然后通过mov指令更新栈帧基准线,与栈顶水位线齐平。...至此红蓝两条线都恢复到了最开始的位置,main函数在栈帧恢复完成。 不准确的说,函数的栈帧就是红蓝两条线之间的内存块,它用来存放函数的临时变量,参数和返回地址。...所谓的保护栈帧恢复栈帧,不过是在保存和恢复寄存器esp和ebp的值。 至于return address是用来做:函数返回的。...随着函数的调用,函数的栈帧会逐层堆叠,但互不重合。 随着函数的逐层返回函数的栈帧会被就地放弃,但不会清理内存。...2 正括号{用来保护上层主调函数(main)的栈帧,并设置被调函数(func)的栈帧,反括号}用来放弃被调函数的栈帧,同时恢复主调函数的栈帧,这样被调函数执行完后,主调函数就能正常执行。
其中 ESP:堆栈指针寄存器,存放执行函数对应栈帧的栈顶地址,且始终指向栈顶。 EBP:栈帧基址指针寄存器,存放执行函数对应栈帧的栈底地址,用于 C 运行库访问栈中的局部变量和参数。...0x02 栈帧 函数调用经常是嵌套的,在同一时刻,堆栈中会有多个函数的信息。每个未完成运行的函数占用一个独立的连续区域,称作栈帧 (Stack Frame)。...栈帧是堆栈的逻辑片段,当调用函数时逻辑栈帧被压入堆栈, 当函数返回时逻辑栈帧被从堆栈中弹出。栈帧存放着函数参数,局部变量及恢复前一栈帧所需要的数据等。...栈帧的边界由栈帧基地址指针 EBP 和堆栈指针 ESP 界定 (指针存放在相应寄存器中)。...EBP 指向当前栈帧底部 (高地址),在当前栈帧内位置固定;ESP 指向当前栈帧顶部 (低地址),当程序执行时 ESP 会随着数据的入栈和出栈而移动。
开发环境 Ubuntu 14.04(32bits) GCC 编辑器 Cmd Markdown 画图工具 Processon 1,函数调用过程 今天先介绍下基本的函数调用过程,即栈帧。...1.1栈帧 每个函数调用都对应一个栈帧。每个栈帧由ESP和EBP寄存器来确定。每个函数执行时,其局部变量都是在自己对应的栈帧内分配内存。...-main .globl test .type test, @function test: .LFB1: .cfi_startproc pushl %ebp //ebp压栈,即old ebp...ident "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2" .section .note.GNU-stack,"",@progbits 当main函数调用test函数时,对应的栈帧见下图...当函数test返回后,main函数的栈帧如下图
本篇介绍 本篇介绍下汇编中的函数,栈帧内容。...栈帧 对于intel处理器,在调用函数的时候需要保证rsp是16字节对齐的,这样设计是为了更好的支持SIMD。那体现到代码上是怎样呢?...本来在调用main函数之前rsp是16字节对齐的,可是在调用main时候,由于会将返回地址压栈,这时候rsp就不是16字节对齐了,就需要prologue中再次执行一个进栈操作,就可以保证是对齐的了。
前置知识 JVM运行时数据区 栈帧的组成 虚拟机栈 与 栈帧 虚拟机栈(JVM Stack),由 栈帧 Frame 组成。...Frame - 每个方法对应一个栈帧, 包括以下部分: Local Variable Table (局部变量表) ?...return address(返回地址) a() -> b(),方法a调用了方法b, b方法的返回值放在什么地方 方法退出时会做的操作: 恢复上一个方法(调用者的栈帧)的Local Variable...Table(局部变量表)和Operand Stack(操作数栈) 将返回的变量压入 上一个方法(调用者的栈帧)的Operand Stack(操作数栈) 调整 Program Counter Register...(PC, 程序计数器) 的值为 当前帧的返回地址 当前栈帧弹出JVM Stack 栈, 执行Program Counter Register (PC, 程序计数器)指向的指令 理解JVM栈帧 用两个代码来帮助理解
这些信息保存在栈帧中,并且栈帧被压入调用栈。 什么是栈帧? 栈帧是调用栈中的基本单元,每个函数调用都会在调用栈中创建一个新的栈帧。栈帧保存了函数执行所需的所有信息,包括局部变量、返回地址、参数等。...函数调用过程 当程序执行到 main 函数时,会首先在调用栈中创建一个栈帧以保存 main 函数的执行状态。然后,main 函数调用 A 函数,系统会在调用栈中为 A 函数创建一个新的栈帧。...随着 A 函数调用 B 函数,调用栈中会继续创建新的栈帧。最终,B 函数调用 C 函数,调用栈中创建了 C 函数的栈帧。 2....调用栈示意图 为了更直观地展示上述过程,我们可以使用 UML 创建一个调用栈的示意图: 栈帧在错误处理中的应用 栈帧在错误处理和调试过程中也非常有用。...结论 程序调用栈和栈帧是理解程序执行原理的重要概念。调用栈管理函数调用的顺序,而栈帧则保存每个函数调用的详细信息。通过掌握这些概念,开发者可以更好地进行调试、错误处理和性能优化。
活动记录(Activation Record),常称栈帧(stack frame)。...---- 嵌套过程 静态链(Static Link) 嵌套函数中,内部函数调用的栈帧可见外部函数调用的栈帧中的变量。...以frame pointer作为第一个参数(不一定是当前的栈帧,而是callee的上层)传递给callee作为static link,可以通过static link回溯上一层、上上层的栈帧,最终获得外部的变量...如果儿子1调用儿子2,那么事实上儿子1是通过父亲访问到的儿子2,因此不能直接传儿子1的栈帧,而是先回溯到父亲的栈帧,再把父亲的栈帧指针作为第一个参数传递给儿子2....F_allocLocal在栈帧上分配局部变量。
大致分布如图: 我们本次所要了解的栈帧属于栈区。...2.栈帧简介 栈帧也叫过程活动记录,是编译器用来实现过程/函数调用的一种数据结构。 函数的每次调用,都有它自己独立的栈帧。...二、函数栈帧介绍 每个函数被调用时都会建立栈帧,在接下来的调试过程中我将会进一步解释。...main() { int a = 15; int b = 30; int c = 0; c = ADD(a, b); printf("%d\n", c); return 0; } 2.如何查看汇编代码...3.函数栈帧的创建与销毁(重点) 该程序的汇编代码如下:(注释有每一步的原理) --- d:\c语言\函数栈帧hszz\函数栈帧hszz\hszz.c -------------------------
---- 函数栈帧的创建和销毁:: ebp,esp这两个寄存器中存放的是地址,这两个地址是用来维护函数栈帧的,edp被称为栈底指针,esp被称为栈顶指针。push:压栈:给栈顶放一个元素。...pop:出栈:给栈顶删一个元素,lea:加载有效地址。dword=4byte。...答:首先为此次函数调用创建函数栈帧,在函数栈帧找空间存放局部变量值。 2.为什么局部变量的值是随机值? 随机值是系统开辟完函数栈帧后系统随机放进去的。 3.函数是怎么传参的?...返回值并不会随着函数作用域的销毁而销毁,而是放在eax中准备返回,当通过pop出栈回到main函数中再将返回值放到局部变量中。
提示:以下是本篇文章正文内容,下面案例可供参考 一、函数栈帧的创建 函数栈帧的创建是在函数调用时进行的,栈帧中包含了局部变量、函数参数、返回地址和调用者的上下文等信息。具体的创建过程如下: 1....函数参数的传递 在函数调用时,参数的值会被压入栈中,这些参数会成为新栈帧的一部分。在栈帧中,函数参数的位置是从高地址到低地址分配的。 2....二、函数栈帧的销毁 函数栈帧的销毁是在函数返回时进行的。在函数返回之前,需要将栈帧中的信息恢复并将其从栈中弹出。具体的销毁过程如下: 1....减小栈指针 在完成上述过程后,需要将栈指针(P)向下移动,以便将当前栈帧从栈中弹出。当栈指针恢复到上一个栈帧的位置时,程序会从该处继续执行,直到遇到下一个函数调用。...栈帧的大小限制: 栈帧的大小是由局部变量、函数参数和其他信息所占用的内存大小决定的。在设计函数时,我们应该合理估计局部变量的大小和数量,避免栈帧过大导致栈溢出。
那么通过学习函数栈帧的创建和销毁,以上困惑就会迎刃而解。...注: 本次讲解使用的是vs2013,不要使用太高级的编译器,越高级的编译器,越不容易学习和观察;同时,在不同的编译器下,函数调用过程中栈帧的创建是略有差异的,具体细节取决于编译器的实现。...为了讲清楚函数栈帧,我们需要先做一些铺垫: 寄存器: eax ebx ecx edx ebp esp ebp、esp这2个寄存器中存放的是地址,这2个地址是用来维护函数栈帧的...每一个函数调用,都要在栈区创建一个空间 接下来,就正式开始介绍函数栈帧的创建和销毁 push ebp mov ebp,esp sub esp,0E4h push ebx push esi push...总结: 局部变量在函数的栈帧里被分配了一些空间进行创建 局部变量不初始化的时候是随机值(比如上述过程中不初始化之前是cccccccc) 函数在调用之前就把参数从右向左进行压栈;真正进入函数后通过指针的偏移量找到形参
---- 1.什么是函数栈帧 函数栈帧( stack frame )就是函数调用过程中在程序的调用栈( call stack )所开辟的空间,这些空间是用来存放: 函数参数和函数返回值...3.函数栈帧的创建和销毁解析 3.1栈 栈( stack )是现代计算机程序里最为重要的概念之一,几乎每一个程序都使用了栈,没有栈就没有函数,没有局部变量,也就没有我们如今看到的所有的计算机语言。...转入目标函数 jump :通过修改 eip ,转入目标函数,进行调用 ret :恢复返回地址,压入 eip ,类似 pop eip 命令 3.3解析函数栈帧的创建和销毁 3.3.1... 基本知识 1.每一次函数调用,都要为本次函数调用开辟空间,就是函数栈帧的空间。...2.这块空间的维护是使用了两个寄存器:esp ebp,ebp记录的是栈底的地址,esp记录的是栈顶的地址。 3.函数栈帧的创建和销毁过程,在不同的编译器上实现的方法大同小异。
、理解栈帧 首先,什么是栈帧?...引用百度百科:C语言中,每个栈帧对应着一个未运行完的函数。栈帧中保存了该函数的返回地址和局部变量。从这句话中,可以提炼以下几点信息: 栈帧是一块因函数运行而临时开辟的空间。...每调用一次函数便会创建一个独立栈帧。 栈帧中存放的是函数中的必要信息,如局部变量、函数传参、返回值等。 当函数运行完毕栈帧将会销毁。 下面进入主题,图解函数栈帧的创建与销毁过程。...在调试过程中将转到反汇编,便能直观的看到main函数栈帧创建的过程。首先需明确的是,函数栈帧由寄存器esp,ebp维护。...进入Add()函数,可以看出这与此前main函数开辟栈帧的过程类似,说明Add()函数调用又开辟了一块独立的栈帧。
领取专属 10元无门槛券
手把手带您无忧上云