全局变量系统将怎样初始化,何时分配内存空间

如题所述

2.1 内存分配策略
按照编译原理的观点,程序运行时的内存分配有三种策略,分别是静态的,栈式的,和堆式的.
静态存储分配是指在编译时就能确定每个数据目标在运行时刻的存储空间需求,因而在编译时就可以给他们分配固定的内存空间.这种分配策略要求程序代码中不允许有可变数据结构(比如可变数组)的存在,也不允许有嵌套或者递归的结构出现,因为它们都会导致编译程序无法计算准确的存储空间需求.
栈式存储分配也可称为动态存储分配,是由一个类似于堆栈的运行栈来实现的.和静态存储分配相反,在栈式存储方案中,程序对数据区的需求在编译时是完全未知的,只有到运行的时候才能够知道,但是规定在运行中进入一个程序模块时,必须知道该程序模块所需的数据区大小才能够为其分配内存.和我们在数据结构所熟知的栈一样,栈式存储分配按照先进后出的原则进行分配。
静态存储分配要求在编译时能知道所有变量的存储要求,栈式存储分配要求在过程的入口处必须知道所有的存储要求,而堆式存储分配则专门负责在编译时或运行时模块入口处都无法确定存储要求的数据结构的内存分配,比如可变长度串和对象实例.堆由大片的可利用块或空闲块组成,堆中的内存可以按照任意顺序分配和释放.
2.2 堆和栈的比较
上面的定义从编译原理的教材中总结而来,除静态存储分配之外,都显得很呆板和难以理解,下面撇开静态存储分配,集中比较堆和栈:
从堆和栈的功能和作用来通俗的比较,堆主要用来存放对象的,栈主要是用来执行程序的.而这种不同又主要是由于堆和栈的特点决定的:
在编程中,例如C/C++中,所有的方法调用都是通过栈来进行的,所有的局部变量,形式参数都是从栈中分配内存空间的。实际上也不是什么分配,只是从栈顶向上用就行,就好像工厂中的传送带(conveyor belt)一样,Stack Pointer会自动指引你到放东西的位置,你所要做的只是把东西放下来就行.退出函数的时候,修改栈指针就可以把栈中的内容销毁.这样的模式速度最快, 当然要用来运行程序了.需要注意的是,在分配的时候,比如为一个即将要调用的程序模块分配数据区时,应事先知道这个数据区的大小,也就说是虽然分配是在程序运行时进行的,但是分配的大小多少是确定的,不变的,而这个"大小多少"是在编译时确定的,不是在运行时.
堆是应用程序在运行的时候请求操作系统分配给自己内存,由于从操作系统管理的内存分配,所以在分配和销毁时都要占用时间,因此用堆的效率非常低.但是堆的优点在于,编译器不必知道要从堆里分配多少存储空间,也不必知道存储的数据要在堆里停留多长的时间,因此,用堆保存数据时会得到更大的灵活性。事实上,面向对象的多态性,堆内存分配是必不可少的,因为多态变量所需的存储空间只有在运行时创建了对象之后才能确定.在C++中,要求创建一个对象时,只需用 new命令编制相关的代码即可。执行这些代码时,会在堆里自动进行数据的保存.当然,为达到这种灵活性,必然会付出一定的代价:在堆里分配存储空间时会花掉更长的时间!这也正是导致我们刚才所说的效率低的原因,看来列宁同志说的好,人的优点往往也是人的缺点,人的缺点往往也是人的优点(晕~).

2.3 JVM中的堆和栈
JVM是基于堆栈的虚拟机.JVM为每个新创建的线程都分配一个堆栈.也就是说,对于一个Java程序来说,它的运行就是通过对堆栈的操作来完成的。堆栈以帧为单位保存线程的状态。JVM对堆栈只进行两种操作:以帧为单位的压栈和出栈操作。
我们知道,某个线程正在执行的方法称为此线程的当前方法.我们可能不知道,当前方法使用的帧称为当前帧。当线程激活一个Java方法,JVM就会在线程的 Java堆栈里新压入一个帧。这个帧自然成为了当前帧.在此方法执行期间,这个帧将用来保存参数,局部变量,中间计算过程和其他数据.这个帧在这里和编译 原理中的活动纪录的概念是差不多的.
从Java的这种分配机制来看,堆栈又可以这样理解:堆栈(Stack)是操作系统在建立某个进程时或者线程(在支持多线程的操作系统中是线程)为这个线程建立的存储区域,该区域具有先进后出的特性。
每一个Java应用都唯一对应一个JVM实例,每一个实例唯一对应一个堆。应用程序在运行中所创建的所有类实例或数组都放在这个堆中,并由应用所有的线程 共享.跟C/C++不同,Java中分配堆内存是自动初始化的。Java中所有对象的存储空间都是在堆中分配的,但是这个对象的引用却是在堆栈中分配,也 就是说在建立一个对象时从两个地方都分配内存,在堆中分配的内存实际建立这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的指针(引用)而已。
具体的说:
温馨提示:内容为网友见解,仅供参考
第1个回答  2013-08-28
全局变量在程序运行时就已被分配,到程序结束时还原给系统。
第2个回答  2017-05-26
创建对象时,在堆里开辟空间,创建几次,开辟几次

全局变量什么时候在内存中申请空间呢?
全局变量在内存中申请空间的时机主要取决于其是否被初始化。未初始化的全局变量通常位于.bss段中,该段在目标文件中并无实际存储空间,仅存在大小信息。目标文件加载时,系统为.bss段分配内存空间。对于具有初始值的全局变量,则一般存储在.data段。在目标文件中,这部分内容存在且占用了实际存储空间。在程...

C++全局变量初始化
全局变量、文件域的静态变量和类的静态成员变量在main执行前进行静态初始化,分配内存并初始化。局部静态变量在第一次使用时分配内存并初始化。这里的变量涵盖了内置数据类型和自定义类型的对象。在函数内部,静态对象的初始化会在第一次运行到函数的那部分代码时发生。假设有一个函数testFun,函数内部的变...

全局变量什么时候分配内存
初始化的全局变量,在程序加载的时候,会从程序文件中,映射(大部分操作系统,只有第一次使用该地址空间时,才加载到内存中)到内存的数据段。未初始化的全局变量部分,映射到进程地址空间的数据段,Unix中,用到该数据的时候,自动0填充。进程的运行过程如下。1)地址映射,代码段,数据段等映射到逻辑...

java中的全局变量和静态变量是在编译时分配内存还是在加载时分配内存...
2.初始化静态属性 。3 .按顺序的初始化静态代码块 初始化的前提就是分配空间 。而且静态变量在以后的创建对象的时候不在初始化 所以一般用静态来保存共享信息 静态变量存在于方法区中,成员变量存在于堆内存中,成员变量所属于对象JAVA成员变量和静态变量的区别,成员变量随着对象创建而存在。随着对象被...

c++中两个局部变量和全局变量,变量名相同,请问内存空间如何分配?
第一点:一个由 c\/C++编译的程序占用的内存分为以下几个部分 1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式 类似于数据结构中的栈。2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由 OS 回收 。注意它与数据结构中的堆是两...

C++局部静态变量在什么时候分配内存和初始化
全局变量是在main函数之前就分配 局部变量在定义时分配,超出作用域后释放 静态局部变量只分配一次,程序退出后才释放 函数参数与局部变量基本上相同在进入函数时分配,函数结束时释放

C 程序中全局变量存储空间在( )分配
2.堆区(heap):一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中堆是两回事,链表数据空间必须采用堆存储分配策。3.全局区(静态区)(static):全局变量和静态变量存储是放在这一块。初始化全局变量和静态变量在一块区域,未初始化全局变量和未初始化静态变量在...

c++ 变量的生命周期和内存的分配释放
全局变量,是全局可见,程序结束后由操作系统收回。常量区,全局存在,程序结束后由操作系统收回。堆区,全局存在,程序员主动申请,主动释放,如果不释放,导致内存不足,于一个常驻进程内存泄漏,导致程序异常,无法继续申请内存,当程序结束后,此部分内存由操作系统收回。栈区,局部存在,系统分配,作用...

给变量分配内存单元是在什么时候进行的?
这个涉及到局部变量还是全局变量的问题,函数中的变量属于局部变量,所以再调用到之后才开辟内存空间,但局部变量所在函数调用完毕,局部变量就被取消了,然后所占内存就被收回了。 而全局变量由于作用域很广,一旦定义,编译器就会分配内存,程序运行期间这块内存单元一直有效,直到整个程序结束才由系统收回内存...

C#变量内存分配时间 和是否初始化
1.在实例化一个C#类时,字段会被默认初始化嘛,会初始化,值类型的初始化为0或false,引用类型初始化为null,但必须要显式赋值,否则无法编译(C#规定使用前必须显式赋值),2.函数内的部变量是不是在函数开始时全部在栈上分配空间(包括程序块内局部变量),如果我只时声明,局部变量会被默认初始...

相似回答