栈 上节我们介绍了函数的基本概念,在最后我们提到了一个系统异常java.lang.StackOverflowError,栈溢出错误,要理解这个错误,我们需要理解函数调用的实现机制。本节就从概念模型的角度谈谈它的基本原理。 我们之前谈过程序执行的基本原理:CPU有一个指令指示器,指向下一条要执行的指令,要么顺序执行,要么进行跳转(条件跳转或无条件跳转)。 基本上,这依然是成立的,程序从main函数开始顺序执行,函数调用可以看做是一个无条件跳转,跳转到对应函数的指令处开始执行,碰到return语句或者函数结尾
先回忆一下前面几节内容:一个.java文件经Javac编译器编译为.class文件(字节码文件), 当我们使用java命令执行该class文件时(HotSpot为例),首先会创建JVM实例,开辟内存空间,然后由类加载器将相应的字节码文件加载到虚拟机内存中,最后找到程序执行入口的main函数, 由JVM创建的main线程调用main函数(线程为执行引擎的的一个实例,并为该线程绑定程序计数器,虚拟机栈),main函数调用的过程中会先创建一个main帧,根据编译时期就已经确定的局部变量数组和操作数栈的大小分配内存空间, 将内存空间清零,将main帧压入main线程虚拟机栈中,main帧执行过程中,如遇到其他方法调用,同样会将调用的方法封装为栈帧压入栈中。
又到了小编和大家说到的时间了,闲话少说,直接上正题,今天就讲讲“C语言程序真正的启动函数”。 为什么要用”真正”这个词?因为我们从学C语言开始,都会先明白这个道理,即C语言有且仅有一个main函数,main函数是C语言的入口点和出口点!(可以参考<<一个C语言程序的基本机构>>http://www.dotcpp.com/wp/184.htmll)不光C语言如此,C++也如此,甚至无论黑窗口的控制台程序和Windows应用程序,都是从main函数或者WinMain函数开始执行,这
一个小问题 在开源中国看到这样一则问题 https://www.oschina.net/question/2507499_2244027,其中的变量a前后的输出是什么? 我答错了,我认为传入funct
最近这段时间,轩辕有些迷茫了,工作生活中一堆事儿,忙得我两头摸黑,很难找到时间静下心来写文章,就连你现在看到的这一篇还是我点灯熬油到1点钟才写完的。
对于JDK的安装和环境配置,网上已经有很多资料,比如:这个是我随便搜的。 至于编辑器的话,我个人使用的是IDEA,因为刚好有教育邮箱,可以免费使用(这一点对于没有收入来源的学生来讲真的很赞) 另外,我是学习过C++的一名普通学生,所以之后的很多内容,我都会相较于C++来比较学习,这样也便于快速理解,或许对于没有C++或类似基础的同胞们不太友好,请谅解。 以下都只是精简地概述,若想更详细地了解,可以去各大网站搜索javaSE教程,会详细地多。
C语言的使用是面向过程的, 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。所以C语言的程序都是以函数作为基本单位的,如果能够深入理解函数,无疑对于c语言会有更深刻地理解,修炼自己的内功,那么函数是如何调用的?函数返回值是如何返回的?函数的形参是如何传递的…………等等的问题,其实都和函数栈帧有关系!
之前的几篇文章中,总结了java中的基本语句和基本数据类型等等一系列的最基本的东西,下面就来说说java中的函数部分
参考 堆内存:https://baike.baidu.com/item/%E5%A0%86%E5%86%85%E5%AD%98/7270805?fr=aladdin 栈内存:https://baike
前面几节我们介绍了CPU寄存器、内存、汇编指令以及栈等基础知识,为了达到融会贯通加深理解的目的,这一节我们来综合运用一下所学知识,看看函数的执行和调用过程。
①函数参数和函数返回值 ②临时变量(包括函数的非静态的局部变量以及编译器自动生产的其他临时变量) ③保持上下文信息(包括在函数调用前后需要保持不变的寄存器)
我们在写C语言代码的时候,经常会把一个独立的功能抽象为函数,所以C程序是以函数为基本单位的。 那函数是如何调用的?函数的返回值又是如何返回的?函数参数是如何传递的?这些问题都和函数栈帧有关系。
1)运行时数据区:经过编译生成的字节码文件(class文件),由class loader(类加载子系统)加载后交给执行引擎执行。在执行引擎执行的过程中产生的数据会存储在一块内存区域。这块内存区域就是运行时区域
存放基本类型的变量,对象的引用和方法调用,遵循先入后出的原则。 栈内存在函数中定义的“一些基本类型的变量和对象的引用变量”都在函数的栈内存中分配。当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。
在前面关于HotSpot组成中提到,运行时数据区就类似一个工厂,是Java程序运行所在的内存区域,这个区域被JVM所管理,按照虚拟机规范的规定将其划分为:方法区、堆、程序计数器,虚拟机栈、本地方法栈五个部分(在HotSpot虚拟机中虚拟机栈和本地方法栈功能上已经合并) 其中方法区和堆在JVM实例创建的时候就开始创建且分配好内存,我们在启动程序过程中可以通过一些参数设置,比如通过-Xms、-Xmx设置堆大小, JDK7中通过-XX:PermSize、-XX:MaxPermSize设置方法区大小(永久代),JDK8通过-XX:MetaspaceSize=N和 -XX:MaxMetaspaceSize=N设置方法区大小(元空间), 而程序计数器,虚拟机栈,本地方法栈是在线程创建时进行分配,所以方法区、堆是线程共享的,而程序计数器、虚拟机栈、本地方法栈是和线程绑定的,是线程私有的。
**什么场景下会有main函数?** 当该python脚本被作为模块(module)引入(import)时,其中的main()函数将不会被执行。 **main函数的作用?** __ name__ == ‘__ main__’是Python的main函数入口。并非说,加入这句才能使用python xxx…
程序在内存中的存储分为三个区域,分别是动态数据区、静态数据区和代码区。函数存储在代码区,全局变量以及静态变量存储在静态数据区,而在程序执行的时候才会在动态数据区产生数据。程序执行的本质就是代码区的指令不断执行,驱使动态数据区和静态数据区产生数据变化。
对于vs来说__tmainCRTStartup函数也由其他函数调用(取决于编译器)
本文稿费80软妹币 砸个广告:各位在网络安全方面有新创作的小伙伴,快将你们的心得砸过来吧~ 文章以word形式发至邮箱: minwei.wang@dbappsecurity.com.cn 有偿投稿,
一.this关键字 体现:当成员变量和函数的局部变量重名时,可以使用this关键字来区别;在构造函数中调用其它构造函数 原理: 代表的是当前对象。 this就是所在函数
抛出异常的时候,异常栈中有所有函数栈,这样就可以找到main函数所在的类。不过也需要注意,这个异常要在主线程抛出,不能在其他线程抛出。
这篇文章是从头贯穿到尾的,让你更加详细的了解函数是什么样在内存里创建,怎么样销毁的,相信家人们读完这篇文章之后能让你眼里的代码变得透明起来(本章不需要过多了解汇编语言,重点是了解函数栈帧怎么创建和销毁的) 注意:这里我们用的是32位平台,用VS2013作为参考。
多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力。
今天@段段提出了一个很好的问题,她发现单元测试时如果开多个线程,主线程运行结束就结束了,并不会等待子线程结束。
另外,小编也有根据以下总结内容,录制了对JVM讲解视频。里面有个用visio画的JVM内部结构图,每部分的作用都有详细讲解,希望能有帮助。网址:https://edu.csdn.net/lecturer/board/10494
✨作者:@平凡的人1 ✨专栏:《C语言从0到1》 ✨一句话:凡是过往,皆为序章 ✨说明: 过去无可挽回, 未来可以改变 ---- 目录 前言😄 什么是栈🔑 什么是函数的栈帧🔑 认识相关寄存器和汇编指令🔑 寄存器🔥 相关的汇编指令:🔥 函数的调用堆栈🔑 函数栈帧的创建🔑 分析栈帧的创建:💧 为什么会出现“烫烫烫”:💧 分析main函数中的核心代码:💧 分析Add函数的传参💧 函数调用过程💧 函数栈帧的销毁下🔑 结语✍ ---- 前言😄 好的,各位,我们前面就已经学过函数的一些相关知识了
想要对上面的这六个问题做出准确深入的回答,我们需要学习函数栈帧的创建和销毁相关知识,在正式进入函数栈帧之前,我们需要了解一些相关的寄存器和汇编指令。
现代的开发工作中,相信绝大部分的同学手头的项目都不是从第零行代码开始搭建的。各个语言都有自己流行的代码框架,如PHP的有Laravel、CodeIgniter、ThinkPHP等等。大家都是在自己的框架的基础上添加自己的业务代码逻辑,开启开发工作。还记得我们团队有位开发同学当时问过我一个问题,我们用xx框架这么重,一个用户请求过来即使什么也不干,都已经进行了那么多次的函数调用了,适合用来做接口开发吗?
栈是什么?栈帧又是什么?在JVM中,main方法调用say方法后,是怎么运行的?本文将详细讲解栈。希望大家学了之后,对栈有更深的了解。
编写有效的代码需要了解堆栈和堆内存,这使其成为学习编程的重要组成部分。不仅如此,新程序员或职场老手都应该完全熟悉堆栈内存和堆内存之间的区别,以便编写有效且优化的代码。
导读|Go的函数调用时参数是通过栈传递还是寄存器传递?使用哪个版本的Go语言能让程序运行性能提升5%?腾讯后台开发工程师涂明光将带你由浅入深了解函数调用,并结合不同版本Go进行实操解答。
当我们编写完java源代码程序后,经过javac编译后,执行java命令执行这个程序时,是怎么一步步的调用到我们程序中的main方法的呢?今天通过查看OpenJdk的源码来揭开它的神秘面纱。
概述 当我们写一个Java类,并重写Main方法,程序就能运行起来。main方法的背后,程序为什么能运行,jvm究竟做了什么处理?要理解这些,就需要了解jvm的设计原理以及启动的流程。 虚拟机的启动入口位于share/tools/launcher/java.c的main方法,整个流程分为如下几个步骤: 1、配置JVM装载环境 2、解析虚拟机参数 3、设置线程栈大小 4、执行Java main方法 jvm启动流程分析 配置JVM装载环境 Java代码执行时需要一个JVM环境,JVM环境的创建包
了解到 C 语言的函数调用,6个以内的参数通过寄存器传递,6个以外的在栈上传递。网上多篇Go的函数调用分析文章,说Go的函数调用时参数都是通过栈传递,自己通过实际运行Go1.17版本函数调用的汇编代码发现,Go的函数调用时参数是通过寄存器传递。对于这点有些好奇,专门写篇文章分析下。
函数栈帧的创建和销毁是程序执行过程中的核心环节,它们直接影响了程序的运行效率和内存管理。在深入探讨这两个过程之前,我们需要先理解什么是函数栈帧。
C语言使用函数调用,我们再熟悉不过了,但是函数调用在内存中究竟发生了什么真的清楚吗?只有搞清楚内存里的内幕,才算完全搞懂函数的调用。
最近在学习C语言的过程中遇到了一些问题,在询问老师和查询相关资料的基础上了解到了函数栈帧的相关概念,对下列问题也有了答案。
eax,ebx,ecx,edx,ebp,esp。画横线的这两个寄存器存放的是地址。这两个地址是用来维护函数栈帧的。
函数栈帧(stack frame)就是函数调用过程中在程序的调用栈(call stack)所开辟的空间,这些空间是用来存放:
注:本文章所使用的编译器是VS2010,由于不同编译器的函数栈帧与销毁略有差异,所以具体细节请读者自行实践!
函数栈帧的创建和销毁在所有编译器中都是大同小异的,不同的编译器会有不同的方式,但是了解到了简单的底层的这些方法后,其他的编译器都是在此基础上修饰,不必深究。
由上可见{}在汇编指令中发挥的作用可不少,函数之间的随意调用和顺利收场都离不开它们。
本篇内容为函数的补充知识点——函数栈帧的创建和销毁。 在本篇内容中,我们将会学习在函数篇章中未提到的一些知识点:
一个限定表尾进行删除(出栈)和插入(入栈)操作的线性表,其过程类似与压子弹与退子弹(后进先出)。 一个由系统自动分配的内存空间,譬如调用函数、创建临时变量时内存空间的创建与销毁。 用于存储函数内部的局部变量、方法调用、函数传参数值等。 由高地址向低地址生长。
上图已经展示了这个过程:从Java的源代码编译成jar包或war包(字节码),最终运行在JVM中。
前言 在上一篇《前端魔法堂——异常不仅仅是try/catch》中我们描述出一副异常及如何捕获异常的画像,但仅仅如此而已。试想一下,我们穷尽一切捕获异常实例,然后仅仅为告诉用户,运维和开发人员页面报了一个哪个哪个类型的错误吗?答案是否定的。我们的目的是收集刚刚足够的现场证据,好让我们能马上重现问题,快速修复,提供更优质的用户体验。那么问题就落在“收集足够的现场证据”,那么我们又需要哪些现场证据呢?那就是异常信息,调用栈和栈帧局部状态。(异常信息我们已经获取了) 本文将围绕上调用栈和栈帧局部状态叙述,准开
将想到的烧烤食物写在便条上,一个食材一个便条,最先想到的食材写在便条上后,放在最下面,依次往上放,最后想到的写在便条上后,放在最上面。
方法跟函数是几乎一样的。所以语法是大差不差的。就多了一点东西。之前我们在c语言里已经很详细讲过了函数。这里就简便的讲一下。
领取专属 10元无门槛券
手把手带您无忧上云