堆 栈 全局静态

合集下载

c++内存分配机制

c++内存分配机制

C++的内存分配机制可以分为四个区域:堆区、栈区、全局/静态存储区和常量存储区。

1. 堆区:动态内存分配区,程序在运行时可以向该区域申请一定大小的内存,用malloc或new来申请,用free或delete来释放。

2. 栈区:存放函数的参数值和局部变量,由编译器自动分配和释放,其操作方式类似于数据结构中的栈。

3. 全局/静态存储区:全局变量和静态变量被存放在此区域中,包括初始化的全局变量和静态变量(空白初始化的全局变量和静态变量也会被存放在此区域),全局变量和静态变量在程序整个运行期间一直被保留。

4. 常量存储区:常量被存放在此区域中,不允许修改。

C++内存分配机制遵循二八定律,即80%的内存空间被80%的程序所使用,而剩下的20%的内存空间则被浪费。

因此,在编写C++程序时,应该尽可能地利用好内存空间,避免内存空间的浪费。

单片机C语言 必知的数据存储与程序编写知识 附单片机应用编程知识介绍

单片机C语言 必知的数据存储与程序编写知识 附单片机应用编程知识介绍

一、五大内存分区内存分成5个区,它们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。

1、栈区(StaCk):FIFo就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区。

里面的变量通常是局部变量、函数参数等。

2、堆区(heap):就是那些由new分配的内存块,它们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。

如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。

3、自由存储区:就是那些由malloc等分配的内存块,它和堆是十分相似的,不过它是用free 来结束自己的生命。

4、全局/静态存储区:全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。

5、常量存储区:这是一块比较特殊的存储区,它们里面存放的是常量,不允许修改(当然,你要通过非正当手段也可以修改,而且方法很多)code/data/stack内存主要分为代码段,数据段和堆栈。

代码段放程序代码,属于只读内存。

数据段存放全局变量,静态变量,常量等,堆里存放自己malloc或new出来的变量,其他变量就存放在栈里,堆栈之间空间是有浮动的。

数据段的内存会到程序执行完才释放。

调用函数先找到函数的入口地址,然后计算给函数的形参和临时变量在栈里分配空间,拷贝实参的副本传给形参,然后进行压栈操作,函数执行完再进行弹栈操作。

字符常量一般放在数据段,而且相同的字符常量只会存一份。

二、C语言程序的存储区域1、由C语言代码(文本文件)形成可执行程序(二进制文件),需要经过编译-汇编-连接三个阶段。

编译过程把C语言文本文件生成汇编程序,汇编过程把汇编程序形成二进制机器代码,连接过程则将各个源文件生成的二进制机器代码文件组合成一个文件。

2、C语言编写的程序经过编译-连接后,将形成一个统一文件,它由几个部分组成。

堆栈及静态数据区详解

堆栈及静态数据区详解

堆、栈及静态数据区详解五大内存分区在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。

栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区。

里面的变量通常是局部变量、函数参数等。

堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。

如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。

自由存储区,就是那些由malloc等分配的内存块,他和堆是十分相似的,不过它是用free 来结束自己的生命的。

全局/静态存储区,全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。

常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改(当然,你要通过非正当手段也可以修改,而且方法很多)明确区分堆与栈在bbs上,堆与栈的区分问题,似乎是一个永恒的话题,由此可见,初学者对此往往是混淆不清的,所以我决定拿他第一个开刀。

首先,我们举一个例子:void f() { int* p=new int[5]; }这条短短的一句话就包含了堆与栈,看到new,我们首先就应该想到,我们分配了一块堆内存,那么指针p呢?他分配的是一块栈内存,所以这句话的意思就是:在栈内存中存放了一个指向一块堆内存的指针p。

在程序会先确定在堆中分配内存的大小,然后调用operator new分配内存,然后返回这块内存的首地址,放入栈中,他在VC6下的汇编代码如下:00401028 push 14h0040102A call operator new (00401060)0040102F add esp,400401032 mov dword ptr [ebp-8],eax00401035 mov eax,dword ptr [ebp-8]00401038 mov dword ptr [ebp-4],eax这里,我们为了简单并没有释放内存,那么该怎么去释放呢?是delete p么?澳,错了,应该是delete []p,这是为了告诉编译器:我删除的是一个数组,VC6就会根据相应的Cookie 信息去进行释放内存的工作。

堆与栈,静态变量和全局变量的区别

堆与栈,静态变量和全局变量的区别

堆与栈,静态变量和全局变量的区别堆与栈,静态变量和全局变量的区别对和栈的主要的区别由以下几点:1、管理方式不同;2、空间大小不同;3、能否产生碎片不同;4、生长方向不同;5、分配方式不同;6、分配效率不同;管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。

空间大小:一般来讲在32位系统下,堆内存可以达到4G的空间,从这个角度来看堆内存几乎是没有什么限制的。

但是对于栈来讲,一般都是有一定的空间大小的,例如,在VC6下面,默认的栈空间大小是1M(好像是,记不清楚了)。

当然,我们可以修改:打开工程,依次操作菜单如下:Project->Setting->Link,在Category 中选中Output,然后在Reserve中设定堆栈的最大值和commit。

注意:reserve最小值为4Byte;commit是保留在虚拟内存的页文件里面,它设置的较大会使栈开辟较大的值,可能增加内存的开销和启动时间。

碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。

对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出,在他弹出之前,在他上面的后进的栈内容已经被弹出,详细的可以参考数据结构,这里我们就不再一一讨论了。

生长方向:对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。

分配方式:堆都是动态分配的,没有静态分配的堆。

栈有2种分配方式:静态分配和动态分配。

静态分配是编译器完成的,比如局部变量的分配。

动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。

分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。

c语言的内存结构

c语言的内存结构

c语言的内存结构C语言是一种高级编程语言,但实际上在计算机中运行时,C语言程序会被编译成可执行文件,然后在计算机内存中运行。

因此,了解C 语言的内存结构对于理解C程序的运行及性能优化至关重要。

C语言的内存结构主要可以分为以下几个部分:栈(Stack)、堆(Heap)、全局内存(Global Memory)和代码区(Code Segment)。

首先是栈(Stack),栈是一种自动分配和释放内存的数据结构。

它用于存储局部变量、函数参数和函数调用信息等。

栈的特点是后进先出(LIFO),也就是最后进入的数据最先被释放。

栈的大小在程序运行时是固定的,一般由编译器设置。

栈的操作速度较快,但内存空间有限。

其次是堆(Heap),堆是一种动态分配和释放内存的数据结构。

它用于存储动态分配的变量、数据结构和对象等。

堆的大小一般由操作系统管理,并且可以在运行时进行动态扩展。

堆的操作相对较慢,因为需要手动分配和释放内存,并且容易产生内存碎片。

全局内存(Global Memory)是用于存储全局变量和静态变量的区域。

全局变量在程序的生命周期内都存在,并且可以在多个函数之间共享。

静态变量作用于其所在的函数内,但是生命周期与全局变量相同。

全局内存由编译器进行分配和管理。

代码区(Code Segment)存储了程序的指令集合,它是只读的。

在程序运行时,代码区的指令会被一条一条地执行。

代码区的大小由编译器决定,并且在程序执行过程中不能修改。

此外,C语言还具有特殊的内存区域,如常量区和字符串常量区。

常量区用于存储常量数据,如字符串常量和全局常量等。

常量区的数据是只读的,且在程序的整个生命周期内存在。

字符串常量区是常量区的一个子区域,用于存储字符串常量。

在C语言中,内存分配和释放是程序员的责任。

通过使用malloc和free等函数,程序员可以在堆中动态地分配和释放内存,从而灵活地管理程序的内存使用。

不过,应当注意避免内存泄漏和野指针等问题,以免出现内存错误和性能问题。

你知道嵌入式c中各变量存储位置吗

你知道嵌入式c中各变量存储位置吗

你知道嵌入式c中各变量存储位置吗
局部变量,局部静态变量,全局变量,全局静态变量区别:
局部变量:栈区
局部静态变量:静态区
全局变量:静态区的常量区
全局静态变量:静态区
在进行C++/C++编程时,需要程序员对内存的了解比较精准。

经常需要操作的内存可分为以下几个类别:
1、栈区(stack)—由编译器自动分配释放,存放函数的参数值,局部变量的值等。

其操作方式类似于数据结构中的栈。

2、堆区(heap)—一般由程序员分配释放,若程序员不释放,程序结束时可能由OS 回收。

注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。

3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。

- 程序结束后有系统释放
4、文字常量区—常量字符串就是放在这里的。

程序结束后由系统释放
5、程序代码区—存放函数体的二进制代码。

以下是一段实际说明的程序代码:
这是一个前辈写的,非常详细
int a = 0; 全局初始化区
char *p1; 全局未初始化区
main()
{
int b; 栈。

内存中堆栈的划分

内存中堆栈的划分

栈和堆的区别 (转) 终于知道区别了(2007-09-12 08:50:49)转载标签:IT/科技一个由 c/C++ 编译的程序占用的内存分为以下几个部分:1 、栈区( stack )—由编译器自动分配释放,存放函数的参数值,局部变量的值等。

其操作方式类似于数据结构中的栈。

2 、堆区( heap )—一般由程序员分配释放,若程序员不释放,程序结束时可能由 OS 回收。

注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。

3 、全局区(静态区)( static )—全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。

程序结束后由有系统释放。

4 、文字常量区—常量字符串就是放在这里的。

程序结束后由系统释放。

5 、程序代码区—存放函数体的二进制代码。

例子程序:这是一个前辈写的,非常详细//main.cppint a = 0; //全局初始化区char *p1; //全局未初始化区main(){int b; 栈char s[] = "abc"; //栈char *p2; //栈char *p3 = "123456"; //123456在常量区,p3在栈上。

static int c =0; //全局(静态)初始化区p1 = (char *)malloc(10);p2 = (char *)malloc(20); //分配得来得10和20字节的区域就在堆区。

strcpy(p1, "123456"); //123456放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。

}栈:在 Windows 下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。

这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在 WINDOWS 下,栈的大小是 2M (也有的说是 1M ,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示 overflow 。

局部变量与全局变量区别栈、堆和静态存储区的区别

局部变量与全局变量区别栈、堆和静态存储区的区别

从作用域看:全局变量具有全局作用域.全局变量只需在一个源文件中定义,就可以作用于所有地源文件.当然,其他不包括全局变量定义地源文件需要用关键字再次声明这个全局变量.个人收集整理勿做商业用途静态局部变量具有局部作用域.它只被初始化一次,自从第一次初始化直到程序与你新内阁结束都一直存在,他和全局变量地区别在于全局变量对所有地函数都是可见地,而静态局部变量只对定义自己地函数体始终可见.个人收集整理勿做商业用途局部变量也只有局部作用域,他是自动对象,他在程序运行期间不是一直存在,而是只在函数执行期间存在,函数地一次调用结束后,变量就被撤销,其所占用地内存也被收回.个人收集整理勿做商业用途静态全局变量也具有全局作用域,他与全局变量地区别在于如果程序包含多个文件地话,他作用于定义它地文件里,不能作用到其他文件里,即被关键字修饰过地变量具有文件作用域.这样即使两个不同地源文件都定义了相同地静态全局变量,他们也是不同地变量.个人收集整理勿做商业用途从分配内存空间看:全局变量、静态局部变量、静态全局变量都在静态存储区分配空间,而局部变量在栈分配空间.全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式.这两者在存储方式上没有什么不同.区别在于非静态全局变量地作用域是整个源程序,当一个源程序由多个源文件组成时,非静态地全局变量在各个源文件中都是有效地.而静态全局变量则限制了其作用域,即只在定义该变量地源文件内有效,在同一源程序地其他源文件中不能使用它.由于静态全局变量地作用域局限于一个源文件内,只能为该源文件内地函数公用,因此可以避免在其他源文件中引起错误.个人收集整理勿做商业用途、静态变量会被放在程序地静态数据存储区里,这样可以在下一次调用地时候还可以保持原来地赋值.这一点是他与堆栈变量和堆变量地区别个人收集整理勿做商业用途、变量用告知编译器,自己仅仅在变量地作用域范围内可见.这一点是他与全局变量地区别.从以上分析可以看出,把局部变量改变为静态变量后是改变了他地存储方式,即改变了他地生存期.把全局变量改变为静态变量后是改变了他地作用域,限制了他地使用范围,因此这个说明符在不同地地方起地作用是不同地.个人收集整理勿做商业用途:、若全局变量仅在单个文件中访问,则可以讲这个变量修改为静态全局变量.、若全局变量仅在单个函数中使用,则可以将这个变量修改为该函数地静态局部变量.、全局变量、静态局部变量、静态全局变量都存放在静态数据存储区.、函数中必须要使用变量地情况:当某函数地返回值为指针类型时,则必须是地局部变量地地址作为返回值,若为类型,则返回为错指针.个人收集整理勿做商业用途个人收集整理勿做商业用途预备知识—程序地内存分配一个由编译地程序占用地内存分为以下几个部分栈区()—由编译器自动分配释放,存放函数地参数值,局部变量地值等.其操作方式类似于数据结构中地栈. 个人收集整理勿做商业用途堆区()—一般由程序员分配释放,若程序员不释放,程序结束时可能由回收 .注意它与数据结构中地堆是两回事,分配方式倒是类似于链表. 个人收集整理勿做商业用途全局区(静态区)()—,全局变量和静态变量地存储是放在一块地,初始化地全局变量和静态变量在一块区域,未初始化地全局变量、未初始化地静态变量在相邻地另一块区域. 程序结束后有系统释放个人收集整理勿做商业用途文字常量区—常量字符串就是放在这里地.程序结束后由系统释放程序代码区—存放函数体地二进制代码.一个正常地程序在内存中通常分为程序段、数据端、堆栈三部分.程序段里放着程序地机器码、只读数据,这个段通常是只读,对它地写操作是非法地.数据段放地是程序中地静态数据.动态数据则通过堆栈来存放.个人收集整理勿做商业用途在内存中,它们地位置如下:内存低端程序段数据段堆栈内存高端个人收集整理勿做商业用途堆栈是内存中地一个连续地块.一个叫堆栈指针地寄存器()指向堆栈地栈顶.堆栈地底部是一个固定地址.堆栈有一个特点就是,后进先出.也就是说,后放入地数据第一个取出.它支持两个操作,和.是将数据放到栈地顶端,是将栈顶地数据取出.在高级语言中,程序函数调用、函数中地临时变量都用到堆栈.为什么呢?因为在调用一个函数时,我们需要对当前地操作进行保护,也为了函数执行后,程序可以正确地找到地方继续执行,所以参数地传递和返回值也用到了堆栈.通常对局部变量地引用是通过给出它们对地偏移量来实现地.另外还有一个基址指针(,在芯片中是),许多编译器实际上是用它来引用本地变量和参数地.通常,参数地相对地偏移是正地,局部变量是负地.当程序中发生函数调用时,计算机做如下操作:首先把参数压入堆栈;然后保存指令寄存器()中地内容,做为返回地址();第三个放入堆栈地是基址寄存器();然后把当前地栈指针()拷贝到,做为新地基地址;最后为本地变量留出一定空间,把减去适当地数值.在函数体中定义地变量通常是在栈上,用, , 等分配内存地函数分配得到地就是在堆上.在所有函数体外定义地是全局量,加了修饰符后不管在哪里都存放在全局区(静态区),在所有函数体外定义地变量表示在该文件中有效,不能到别地文件用;在函数体内定义地表示只在该函数体内有效.另外,函数中地""这样地字符串存放在常量区.对比:个人收集整理勿做商业用途性能栈:栈存在于中.栈是动态地,它地存储速度是第二快地.堆:堆位于中,是一个通用地内存池.所有地对象都存储在堆中.申请方式【栈】: 由系统自动分配. 例如,声明在函数中一个局部变量; 系统自动在栈中为开辟空间 .【堆】: 需要程序员自己申请,并指明大小,在中函数如( *)(); 在中用运算符如( *)(); 但是注意:、本身是在栈中地.申请后系统地响应栈【】:只要栈地剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出. 个人收集整理勿做商业用途堆【】:首先应该知道操作系统有一个记录空闲内存地址地链表,当系统收到程序地申请时,会遍历该链表,寻找第一个空间大于所申请空间地堆结点,然后将该结点从空闲结点链表中删除,并将该结点地空间分配给程序;另外,对于大多数系统,会在这块内存空间中地首地址处记录本次分配地大小,这样,代码中地语句才能正确地释放本内存空间.另外,由于找到地堆结点地大小不一定正好等于申请地大小,系统会自动地将多余地那部分重新放入空闲链表中.申请大小地限制栈【】:在下,栈是向低地址扩展地数据结构,是一块连续地内存地区域.这句话地意思是栈顶地地址和栈地最大容量是系统预先规定好地,在下,栈地大小是(也有地说是,总之是一个编译时就确定地常数),如果申请地空间超过栈地剩余空间时,将提示.因此,能从栈获得地空间较小. 个人收集整理勿做商业用途堆【】:堆是向高地址扩展地数据结构,是不连续地内存区域.这是由于系统是用链表来存储地空闲内存地址地,自然是不连续地,而链表地遍历方向是由低地址向高地址.堆地大小受限于计算机系统中有效地虚拟内存.由此可见,堆获得地空间比较灵活,也比较大.申请效率地比较栈【】:由系统自动分配,速度较快.但程序员是无法控制地. 个人收集整理勿做商业用途堆【】:是由分配地内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便.另外,在下,最好地方式是用分配内存,他不是在堆,也不是在栈是直接在进程地地址空间中保留一快内存,虽然用起来最不方便.但是速度快,也最灵活.堆和栈中地存储内容栈【】:在函数调用时,第一个进栈地是主函数中后地下一条指令(函数调用语句地下一条可执行语句)地地址,然后是函数地各个参数,在大多数地编译器中,参数是由右往左入栈地,然后是函数中地局部变量.注意静态变量是不入栈地. 个人收集整理勿做商业用途当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存地地址,也就是主函数中地下一条指令,程序由该点继续运行.堆【】:一般是在堆地头部用一个字节存放堆地大小.堆中地具体内容有程序员安排.存取效率地比较[] "";* "";是在运行时刻赋值地;而是在编译时就确定地;但是,在以后地存取中,在栈上地数组比指针所指向地字符串(例如堆)快.比如:(){;[] "";* "";[];[];;}对应地汇编代码: [];[][]: [];[][][]第一种在读取时直接就把字符串中地元素读到寄存器中,而第二种则要先把指针值读到中,在根据读取字符,显然慢了.小结:堆和栈地区别可以用如下地比喻来看出:使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他地好处是快捷,但是自由度小.使用堆就象是自己动手做喜欢吃地菜肴,比较麻烦,但是比较符合自己地口味,而且自由度大.个人收集整理勿做商业用途。

编译原理程序运行时的存储组织

编译原理程序运行时的存储组织

编译原理程序运行时的存储组织一、程序的应该存储区域1.代码区:也称为文本区或者只读区,用于存放程序的目标代码。

代码区是只读的,不允许修改。

在程序运行过程中,代码区的内容不会发生变化。

2.全局数据区:用于存放全局变量和静态数据。

全局数据区在程序开始运行时就被分配好空间,在程序的整个运行过程中都存在,直到程序结束。

3.堆区:用于存放动态分配的内存空间,也称为动态内存分配区。

堆区的内存空间是在程序运行时动态分配和释放的,可以根据程序的需要进行扩大或者缩小。

4.栈区:用于存放函数的局部变量和函数调用信息。

栈区的空间是在程序运行时自动分配和释放的,由编译器负责管理。

在函数调用时,会为函数分配一块栈区空间,函数返回后,该空间被自动释放。

二、内存管理方式1.静态内存管理:静态内存管理是指在程序编译阶段,由编译器根据程序的静态内存需求,在编译过程中为程序分配好固定大小的内存空间,静态内存管理的特点是内存空间的分配和释放都是在编译时确定的,程序运行时不需要进行内存管理。

2.动态内存管理:动态内存管理是指在程序运行时根据需要动态地分配和释放内存空间,动态内存管理的特点是内存空间的分配和释放是在程序运行过程中动态确定的。

动态内存管理可以通过堆区进行。

三、内存分配和释放编译原理程序在运行时的存储组织中,对于静态内存区域的分配和释放是由编译器在编译时确定的,程序在运行时无法进行修改。

对于动态内存区域的分配和释放,可以通过堆区进行,可以使用以下几个函数进行动态内存的分配和释放:1. 分配内存:程序可以使用malloc函数、calloc函数或者realloc函数来分配内存空间。

malloc函数用于分配指定字节数的内存空间,calloc函数用于分配指定数量和大小的内存空间,realloc函数用于调整已经分配的内存空间的大小。

2. 释放内存:程序在使用完动态分配的内存空间后,需要使用free函数来释放内存空间。

free函数会将之前分配的内存空间标记为可用状态,可以供其他程序使用。

全局变量和静态变量

全局变量和静态变量
全局变量和静态变量有相同点,就是在编译的时候分配内存,因为内存分配是非动态的,所以在程序中如果用static修饰,分配容量就确定了。但是,全局变量和静态变量还是有区别的,在于其内部连接上。
c++和C的划分存储区有点不一样。大概可以分为下面5个:
全局/静态区。常量区。自由存储区(new的地方),堆栈(局部变量),堆(malloc)的地方。
其实我觉得自由存储和heap应该差不多。从这点看。全局和静态地方是一样的。可是不能
从这点就说这两个变量是一样的。最起码局部变量都是以静态存储方式存储的。但全局变量具有外部连接性,即同一工程中其它文件中的也可引用。而静态变量不具有外部连接性,即同一工程中其它文件中不可以引用。

C语言内存管理堆栈和静态存储区

C语言内存管理堆栈和静态存储区

C语言内存管理堆栈和静态存储区C语言内存管理:堆、栈和静态存储区C语言作为一种高效而强大的编程语言,其内存管理是程序员必须掌握的重要内容之一。

本文将重点介绍C语言中的内存管理中的堆、栈以及静态存储区。

一、堆堆是C语言中用于动态内存分配的一块内存区域。

在程序运行时,可以通过函数malloc()和calloc()来申请堆空间,通过函数free()来释放堆空间。

堆的特点:1. 大小可变:堆中的内存空间大小可以在程序运行时进行动态调整。

2. 生命周期自由控制:通过malloc()或calloc()分配的堆空间,在不再使用后,需要程序员手动调用free()函数进行释放。

堆的使用场景:1. 动态数组:当程序无法预先知道数组大小时,可以使用堆来动态申请空间。

2. 链表:链表结构通常需要通过堆来进行动态内存分配。

二、栈栈是C语言中用于函数调用和局部变量存储的一块内存区域。

在函数调用过程中,栈会记录函数的调用顺序、调用参数以及局部变量等。

栈的特点:1. 后进先出:栈是一种后进先出(LIFO)的数据结构,函数调用时会依次将函数入栈,并在函数返回时依次出栈。

2. 自动管理:栈内存的分配和释放是由编译器自动完成的,程序员无需手动管理。

栈的使用场景:1. 函数调用:栈用于管理函数的调用顺序以及函数内部的局部变量。

2. 递归:递归函数的调用过程涉及到栈的递归压栈和递归出栈。

三、静态存储区静态存储区是C语言中使用static关键字声明的变量所存储的内存区域。

在程序运行期间,静态变量在内存中的位置始终不变,且仅在程序结束时才会释放。

静态存储区的特点:1. 生命周期长:静态变量在程序运行期间都存在,不依赖于函数的调用和返回。

2. 全局可访问:静态变量可以在整个程序中被访问,不受函数作用域的限制。

静态存储区的使用场景:1. 全局变量:使用static关键字声明的全局变量存储在静态存储区中,可以在整个程序中被访问。

2. 共享数据:多个函数之间需要共享的数据可以使用静态变量来实现。

代码段、数据段、堆栈段、数据段辨析

代码段、数据段、堆栈段、数据段辨析

代码段、数据段、堆栈段、数据段辨析1、⾼位地址:栈(存放着局部变量和函数参数等数据),向下⽣长(可读可写可执⾏)2、堆(给动态分配内存是使⽤),向上⽣长(可读可写可执⾏)3、数据段(保存全局数据和静态数据) (可读可写不可执⾏)4、地位地址:代码段(保存代码)(可读可执⾏不可写)代码段就是存储程序⽂本的,所以有时候也叫做⽂本段,指令指针中的指令就是从这⾥取得。

这个段⼀般是可以被共享的,⽐如你在Linux 开了2个Vi来编辑⽂本,那么⼀般来说这两个Vi是共享⼀个代码段的,但是数据段不同(这点有点类似C++中类的不同对象共享相同成员函数)。

数据段是存储数据⽤的,还可以分成初始化为⾮零的数据区,BSS,和堆(Heap)三个区域。

初始化⾮零数据区域⼀般存放静态⾮零数据和全局的⾮零数据。

BSS是Block Started by Symbol的缩写,原本是汇编语⾔中的术语。

该区域主要存放未初始化的全局数据和静态数据。

还有就是堆了,这个区域是给动态分配内存是使⽤的,也就是⽤malloc等函数分配的内存就是在这个区域⾥的。

它的地址是向上增长的。

最后⼀个堆栈段(注意,堆栈是Stack,堆是Heap,不是同⼀个东西),堆栈可太重要了,这⾥存放着局部变量和函数参数等数据。

例如递归算法就是靠栈实现的。

栈的地址是向下增长的。

具体如下:========⾼地址 =======程序栈堆栈段向下增长“空洞” =======向上增长堆------ 数据段BSS------⾮零数据=========低地址 ================ =======代码代码段========= =======需要注意的是,代码段和数据段之间有明确的分隔,但是数据段和堆栈段之间没有,⽽且栈是向下增长,堆是向上增长的,因此理论上来说堆和栈会“增长到⼀起”,但是操作系统会防⽌这样的错误发⽣,所以不⽤过分担⼼。

C++中堆和栈的完全解析

C++中堆和栈的完全解析

C++中堆和栈的完全解析内存分配方面:堆:操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样代码中的delete语句才能正确的释放本内存空间。

我们常说的内存泄露,最常见的就是堆泄露(还有资源泄露),它是指程序在运行中出现泄露,如果程序被关闭掉的话,操作系统会帮助释放泄露的内存。

栈:在函数调用时第一个进栈的主函数中的下一条指令(函数调用语句的下一条可执行语句)的地址然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈,然后是函数中的局部变量。

一、预备知识—程序的内存分配一个由c/C++编译的程序占用的内存分为以下几个部分1、栈区(stack)—由编译器自动分配释放,存放函数的参数值,局部变量的值等。

其操作方式类似于数据结构中的栈。

2、堆区(heap)—一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。

注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。

3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。

- 程序结束后有系统释放4、文字常量区—常量字符串就是放在这里的。

程序结束后由系统释放5、程序代码区—存放函数体的二进制代码。

有些说法,把3,4合在一起,也有的把3分成自由存储区(malloc/free)和全局/静态存储区。

这与编译器和操作系统有关。

二、例子程序这是一个前辈写的,非常详细//main.cppint a = 0; 全局初始化区char *p1; 全局未初始化区main(){int b; 栈char s[] = "abc"; 栈//更正:abc 分配在静态存储区,不是栈上char *p2; 栈char *p3 = "123456"; 123456\0在常量区,p3在栈上。

局部变量、全局变量、堆、堆栈、静态和全局变量

局部变量、全局变量、堆、堆栈、静态和全局变量

局部变量、全局变量、堆、堆栈、静态和全局变量一般全局变量存放在数据区,局部变量存放在栈区,动态变量存放在堆区,函数代码放在代码区。

---------------------------------------------------------------栈区是普通的栈数据结构,遵循LIFO后进先出的规则,局部变量安排在那里是ASM时就规定的,这样可以在一个函数结束后平衡堆栈,操作简单,效率高堆(动态区)在这里应当叫堆栈(不要和数据结构中的堆搞混)是程序在编译时产生的一块用于产生动态内存分配使用的块,操作比较栈要麻烦许多,在分配时要判断最优的地址(防止产生无用的内存碎片(由于屡次的NEW和DELETE产生的夹在两块使用中内存中的空余小内存(不容易被分配))),分配和回收时的效率比栈低多了---------------------------------------------------------------栈是系统提供的功能,特点是快速高效,缺点是有限制,数据不灵活;而堆是函数库提供的功能,特点是灵活方便,数据适应面广泛,但是效率>有一定降低。

栈是系统数据结构,对于进程/线程是唯一的;堆是函数库内部数据结构,不一定唯一。

不同堆分配的内存无法互相操作。

栈空间分静态分配和动态分配两种。

静态分配是编译器完成的,比如自动变量(auto)的分配。

动态分配由malloca函数完成。

栈的动态分配无需释放(是自动的),也就没有释放函数。

为可移植的程序起见,栈的动态分配操作是不被鼓励的!堆空间的分配总是动态的,虽然程序结束时所有的数据空间都会被释放回系统,但是精确的申请内存/ 释放内存匹>配是良好程序的基本要素。

堆是程序员管理的,栈是系统管理的.另外关于静态和全局的一些问题:静态变量的特点:1、一次存储:静态局部变量只被初始化一次,下一次初始化根据上一次的结果值,有点类似于c++中类的静态成员变量,即无论该类型生成多少个实例对象,所有的对象共用一个静态变量,到这里就是无论这个函数调用多少次,该静态变量只初始化一次,并没有因为超出其生存期而被销毁,只是外部不可见而已,用个例子说明之:void fun1( int v ){static int value = v;static int value = v;}int main( int arc, char*args[ ]){fun1( 50 );fun1( 100 );}执行的结果是:value : 50 value : 50说明在第二次调用fun1( )时的初始化value的采用的是上一次value的值,value在静态区的存储空间并没有因为fun1( )的结束而被释放,即体现了一次存储;2、作用域限定:静态修饰的作用域限定功能同时体现在函数与变量上;a)对于函数而言,任何用static修饰的函数,其作用域仅为当前源文件,而对外部来说这个函数是不可见的,即只有和其在同一源文件中的函数才能调用这个静态函数;反过来说,如果一个函数仅仅被同一源文件中的其他函数调用,那么这个函数应该声明为静态的,这样做的好处在于:可以一定程度上的解决不同源文件之间函数的命名冲突问题;b)对于变量而言,static修饰的全局变量,只在当前源文件中有效,对外部不可见,外部文件不能够引用;顾名思义,全局变量是指能够在全局引用的变量,相对于局部变量的概念,也叫外部变量;同静态变量一样,全局变量位于静态数据区,全局变量一处定义,多处引用,用关键字“extern”引用“外部”的变量。

堆栈的区别

堆栈的区别
00401070 8A 42 01 mov al,byte ptr [edx+1]
00401073 88 45 FC mov byte ptr [ebp-4],al
第一种在读取时直接就把字符串中的元素读到寄存器cl中,而第二种则要先把指针值读到edx中,在根据edx读取字符,显然慢了。
栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。
4、大小限制方面:
堆:是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。
}
二、堆和栈的理论知识
2.1申请方式
stack:
由系统自动分配。 例如,声明在函数中一个局部变量 int b; 系统自动在栈中为b开辟空间
heap:
需要程序员自己申请,并指明大小,在c中malloc函数
如p1 = (char *)malloc(10);
在C++中用new运算符
是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。
明确区分堆与栈
在bbs上,堆与栈的区分问题,似乎是一个永恒的话题,由此可见,初学者对此往往是混淆不清的,所以我决定拿他第一个开刀。

计算机中堆栈的概念

计算机中堆栈的概念

计算机中堆栈的概念这两天学习win32的API,了解到了计算机中堆栈的概念,相信很多程序员有时候也弄不明⽩计算机中的堆栈的。

再次为堆栈做⼀下详细解析。

在英⽂中,我们管栈称为stack,管堆称为heap。

在计算机中,堆栈是两种不同的数据结构,但堆栈均为⼀种按序排列的数据结构。

只能在⼀端对数据项进⾏插⼊和删除。

其中的关键是,堆,的排列顺序是随意的,⽽栈,排列顺序是先进后出(First In Last Out)。

堆:为编译器⾃动的分配与释放,⽤来存放函数的参数值与局部变量。

其操作⽅式类似于数据结构中的栈。

栈使⽤的是⼀级缓存,通常都是在调⽤时候存储于存储空间中,在⽤完后由编译器⾃动的释放。

堆:为编程⼈员分配与释放,如果在程序结束的时候没有释放,⼀般会被OS所回收,分配⽅式类似于链表。

堆⼀般存储于⼆级缓存。

数据结构,堆可以被看成⼀棵树。

栈则是⼀种先进后出的数据结构。

在具体介绍之前,我们应该介绍⼀下在C或者C++语⾔中变量的存储区域。

1,栈区(stack):这块区域由编译器分配与释放内存空间,⼀般存储函数的参数值与局部变量值。

类似于数据结构中的栈。

2,堆区(heap):这块区域由程序员⾃⼰分配与释放,其余数据结构中的堆是两码事,分配⽅式类似于链表。

3,全局区(静态变量区):这块存储区域⽤于存储全局变量(global)和静态变量(static),初始化的全局变量和静态变量存储于⼀块区域,未初始化的全局变量和静态变量存储于另⼀块区域。

程序结束后系统⾃动释放。

4,⽂字常量区(静态缓冲区):这块区域⽤于存储常量静态字符串,在前⾯⽂章我有提到过并且演⽰过,⽤于存放const char*类型的变量。

在程序运⾏中,是不可能对其进⾏修改的,如果修改的话,程序将会报错并且crush,程序结束后由系统⾃动释放。

5,程序代码区:该区域⽤于存放函数体的⼆进制代码。

下⾯,我⽤⼀段程序来解释在什么地⽅存放各种变量。

上⾯的例⼦完全诠释了各种变量存储的地⽅在程序中。

STM32堆栈分析

STM32堆栈分析

三、STM32堆栈区预备知识:一个由C/C++编译的程序占用的内存分为以下几个部分:●栈区(stack):编译器自动分配释放,存放函数的参数值,局部变量的值等。

操作方式类似于数据结构中的栈。

●堆区(heap):一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。

注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。

●全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。

程序结束后由系统释放。

●文字常量区—常量字符串就是放在这里的。

程序结束后由系统释放●程序代码区—存放函数体的二进制代码编译后,各个区存储内容举例说明如下://main.cppint a = 0; 全局初始化区char *p1; 全局未初始化区main(){int b; 栈char s[] = “abc”; 栈char *p2; 栈char *p3 = “123456”; 123456\0在常量区,p3在栈上static int c =0;全局(静态)初始化区p1 = (char *)malloc(10);p2 = (char *)malloc(20);分配得来得10和20字节的区域就在堆区。

strcpy(p1, "123456"); 123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。

}STM32的分区STM32的分区从0x2000 0000(0x2000 0000是SRAM的起始地址,由此可知,堆栈等都是在RAM中的)开始。

静态区,堆,栈。

所有的全局变量,包括静态变量之类的,全部存储在静态存储区。

紧跟静态存储区之后的,是堆区(如没用到malloc,则没有该区),之后是栈区,栈在程序中存储局部变量。

先看启动文件startup_stm32f10x_md.s的定义:; Amount of memory (in bytes) allocated for Stack; Tailor this value to your application needs; <h> Stack Configuration; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>; </h>Stack_Size EQU 0x00000400AREA STACK, NOINIT, READWRITE, ALIGN=3Stack_Mem SPACE Stack_Size__initial_sp; <h> Heap Configuration; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>; </h>Heap_Size EQU 0x00000200AREA HEAP, NOINIT, READWRITE, ALIGN=3__heap_baseHeap_Mem SPACE Heap_Size__heap_limit这里定义了堆栈各自大小,堆:512bytes 栈1k;所以栈区大小有限制,我们在局部变量中不要定义大数组否则容易溢出。

BSS段,数据段,代码段,堆内存和栈

BSS段,数据段,代码段,堆内存和栈
明确区分堆与栈:
在bbs上,堆与栈的区分问题,似乎是一个永恒的话题,由此可见,初学者对此往往是混淆不清的,所以我决定拿他第一个开刀。
首先,我们举一个例子:
void f()
{
int* p=new int[5];
}
这条短短的一句话就包含了堆与栈,看到new,我们首先就应该想到,我们分配了一块堆内存,那么指针 p呢?他分配的是一块栈内存,所以这句话的意思就是:在栈内存中存放了一个指向一块堆内存的指针p。在程序会先确定在 堆中分配内存的大小,然后调用operator new分配内存,然后返回这块内存的首地址,放入栈中,他在VC6下的汇编代码如下:
1. 系统调用可能不支持任意大小的内存分配。有些系统的系统调用只支持固定大小及其倍数的内存请求(按页分配);这样的话对于大量的小内存分类来说会造成浪 费。
2. 系统调用申请内存可能是代价昂贵的。系统调用可能涉及用户态和核心态的转换。
3. 没有管理的内存分配在大量复杂内存的分配释放操作下很容易造成内存碎片。
int a = 0; //全局初始化区
char *p1; //全局未初始化区
void maiห้องสมุดไป่ตู้()
{
int b; //栈
char s[] = "abc"; //栈
char *p2; //栈
char *p3 = "123456"; //123456{post.content}在常量区,p3在栈上
数据段:数据段(data segment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。
代码段:代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。代码段是存放了程序代码的数据,假如机器 中有数个进程运行相同的一个程序,那么它们就可以使用同一个代码段。

omp静态分配和动态分配

omp静态分配和动态分配

omp静态分配和动态分配
静态分配和动态分配的区别主要是两个:
一是时间不同。

静态分配发生在程序编译和连接的时候。

动态分配则发生在程序调入和执行的时候。

二是空间不同。

堆都是动态分配的,没有静态分配的堆。

栈有2种分配方式:静态分配和动态分配。

静态分配是编译器完成的,比如局部变量的分配。

动态分配由函数omp进行分配。

不过栈的动态分配和堆不同,他的动态分配是由编译器进行释放,无需我们手工实
现。

对于一个进程的内存空间而言,可以在逻辑上分成3个部份:代码区,静态数据区和动态数据区。

动态数据区一般就是“堆栈”。

“栈(stack)”和“堆(heap)”是两种不同的动态数据区,栈是一种线性结构,堆是一种链式结构。

进程的每个线程都有私有的“栈”,所以每个线程虽然代码一样,但本地变量的数据都是互不干扰。

一个堆栈可以通过“基地址”和“栈顶”地址来描述。

全局变量和静态变量分配在静态数据区,本地变量分配在动态数据区,即堆栈中。

程序通过堆栈的基地址和偏移量来访问本地变量。

c++程序语言特点

c++程序语言特点

c++程序语言特点c++程序语言特点C语言是1972年由美国贝尔实验室的D.M.Ritchie研制成功的。

它不是为初学者设计的,而是为计算机专业人员设计的。

下面是店铺搜集的c++程序语言特点,希望大家认真阅读!1. C++内存可分为以下区域:全局/静态数据区常量数据区(其中的数据不能被修改)代码区堆栈备注:全局/静态区,常量数据区实际上都在进程的数据区中。

2.堆和栈上分配内存的性能比较:(1) 栈上的内存是系统自动分配的,不需要用户主动分配和释放;(2) 栈上分配的内存效率比较高(不需要经过堆管理器分配,一系列查找空闲堆的逻辑);(3) 栈上分配的内存,是连续的,不会导致内存碎片。

3. 虚函数表指针虚函数表的指针,占据类对象内存最开始的4个字节。

(1)存放位置:类对象开始的4个字节存放的是虚函数表的指针,而虚函数表本身放在常量区。

(2)创建时机:在对象创建时,构造函数中会调用编译器在构造函数内部插入的初始化代码,来初始化虚函数指针,使其指向正确的虚函数表。

(这就解释了为什么构造函数不能是虚函数的问题)4. this指针类的非静态成员函数,都会默认的`传this指针作为参数,以便在函数内部可以通过this指针访问相应的类对象。

在进入函数体前创建并传参,在函数返回时销毁。

5. 类对象的创建过程首先,申请该对象对应的内存;其次,对类对象进行初始化,即调用类的构造函数。

包括两个步骤:执行初始化列表;执行构造函数体。

注意:常量和引用类型的变量,必须在初始化列表中进行初始化。

6. 内联函数的声明内联函数声明有两种方式,通常我们只知道第一种:(1)显式声明:用“inline”关键字声明;(2)隐式声明:在类内声明成员函数时,同时提供其函数体实现,这时候函数会被定义成内联函数,不需要“inline”关键字声明。

例如:Class Student{public:String GetName() { return name; }}内联函数的优点:(1) 避免一般函数调用的参数压栈,栈帧开辟与回收,寄存器保存与恢复等开销;(2) 由于编译时函数代码是完全展开的,编译器可以对调用函数处的代码做更深入的优化。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

C++中,内存分为5个区:堆、栈、自由存储区、全局/静态存储区和常量存储区。

栈:是由编译器在需要时自动分配,不需要时自动清除的变量存储区。

通常存放局部变量、函数参数等。

堆:是由new分配的内存块,由程序员释放(编译器不管),一般一个new与一个delete 对应,一个new[]与一个delete[]对应。

如果程序员没有释放掉,资源将由操作系统在程序结束后自动回收。

自由存储区:是由malloc等分配的内存块,和堆十分相似,用free来释放。

全局/静态存储区:全局变量和静态变量被分配到同一块内存中(在C语言中,全局变量又分为初始化的和未初始化的,C++中没有这一区分)。

常量存储区:这是一块特殊存储区,里边存放常量,不允许修改。

(注意:堆和自由存储区其实不过是同一块区域,new底层实现代码中调用了malloc,new 可以看成是malloc智能化的高级版本)
堆与栈的讨论:
管理方式:
堆中资源由程序员控制(容易产生memory leak)。

栈资源由编译器自动管理,无需手工控制。

系统响应:
对于堆,应知道系统有一个记录空闲内存地址的链表,当系统收到程序申请时,遍历该链表,寻找第一个空间大于申请空间的堆结点,删除空闲结点链表中的该结点,并将该结点空间分配给程序(大多数系统会在这块内存空间首地址记录本次分配的大小,这样delete 才能正确释放本内存空间,另外系统会将多余的部分重新放入空闲链表中)。

对于栈,只要栈的剩余空间大于所申请空间,系统为程序提供内存,否则报异常提示栈溢出。

空间大小:
堆是不连续的内存区域(因为系统是用链表来存储空闲内存地址,自然不是连续的),堆大小受限于计算机系统中有效的虚拟内存(32bit系统理论上是4G),所以堆的空间比较灵活,比较大。

栈是一块连续的内存区域,大小是操作系统预定好的,windows下栈大小是2M(也有是1M,在编译时确定,VC中可设置)。

碎片问题:
对于堆,频繁的new/delete会造成大量碎片,使程序效率降低。

对于栈,它是一个先进后出的队列,进出一一对应,不会产生碎片。

生长方向:
堆向上,向高地址方向增长。

栈向下,向低地址方向增长。

分配方式:
堆都是动态分配(没有静态分配的堆)。

栈有静态分配和动态分配,静态分配由编译器完成(如局部变量分配),动态分配由alloca 函数分配,但栈的动态分配的资源由编译器进行释放,无需程序员实现。

分配效率:
堆由C/C++函数库提供,机制很复杂。

所以堆的效率比栈低很多。

栈是极其系统提供的数据结构,计算机在底层对栈提供支持,分配专门寄存器存放栈地址,栈操作有专门指令。

相关文档
最新文档