堆区和自由存储区是不是同一概念?

追求执着 2011-10-18 01:58:16
在看内存管理中,有的文章中提到了使用malloc()创建的内存是在堆中,但也称作对为自由存储区;但同时在另外的一些文章中提到说堆和自由存储区相似,但不相同,使用malloc()是在自由存储区中进行申请内存,使用new是在堆中创建,求解答...
...全文
352 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
w263044840 2011-10-19
  • 打赏
  • 举报
回复
但是我记得前几天看汇编还说new和malloc最终调用的都是同一个api函数呢,怎么会不同呢
追求执着 2011-10-19
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 zhao4zhong1 的回复:]
某块内存的分配和释放只是和‘操作系统内存管理模块’交流而已。
其实那块内存的值完全可以绕过‘操作系统内存管理模块’去读写。
[/Quote]
不同的操作系统有不同的内存管理方式,对于开发语言来讲,只是通过共同的接口去实现,而具体的内存管理需要操作系统来实现?
赵老师,是这个意思吗?太高深,有时理解不来.
赵4老师 2011-10-19
  • 打赏
  • 举报
回复
某块内存的分配和释放只是和‘操作系统内存管理模块’交流而已。
其实那块内存的值完全可以绕过‘操作系统内存管理模块’去读写。
梦境传说 2011-10-19
  • 打赏
  • 举报
回复
C++中的堆、栈、自由存储区、全局/静态存储区和常量存储区:


1.栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区。里面的变量通常是局部变量、函数参数等。

2.堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。

3.自由存储区,就是那些由malloc等分配的内存块,他和堆是十分相似的,不过它是用free来结束自己的生命的。(补充:自由存储区和堆不是一个概念。一般而言,自由存储区是指CRT(C运行时库)通过malloc,free函数管理的内存。堆特指通过new,delete管理的内存。但是在部分编译器的实现上这两块内存都是同一种管理方式。)

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

5.常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改(当然,你要通过非正当手段也可以修改,而且方法很多)。


堆和栈究竟有什么区别?
主要的区别由以下几点:
1、管理方式不同;对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。[Page]
2、空间大小不同;一般来讲在32位系统下,堆内存可以达到4G的空间,从这个角度来看堆内存几乎是没有什么限制的。但是对于栈来讲,一般都是有一定的空间大小的,例如,在VC6下面,默认的栈空间大小是1M(好像是,记不清楚了)。当然,我们可以修改:打开工程,依次操作菜单如下:Project->Setting->Link,在Category 中选中Output,然后在Reserve中设定堆栈的最大值和commit。注意:reserve最小值为4Byte;commit是保留在虚拟内存的页文件里面,它设置的较大会使栈开辟较大的值,可能增加内存的开销和启动时间。
3、能否产生碎片不同;对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题, 因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出,在他弹出之前,在他上面的后进的栈内容已经被弹出,详细的 可以参考数据结构,这里我们就不再一一讨论了。
4、生长方向不同;对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。
5、分配方式不同;堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。
6、分配效率不同;栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。

从这里我们可以看到,堆和栈相比,由于大量new/delete的使用,容易造成大量的内存碎片;由于没有专门的系统支持,效率很低;由于可能引发用户态和核心态的切换,内存的申请,代价变得更加昂贵。所以栈在程序中是应用最广泛的,就算是函数的调用也利用栈去完成,函数调用过程中的参数,返回地址,EBP和局部变量都采用栈的方式存放。所以,我们推荐大家尽量用栈,而不是用堆。
虽然栈有如此众多的好处,但是由于和堆相比不是那么灵活,有时候分配大量的内存空间,还是用堆好一些。

无论是堆还是栈,都要防止越界现象的发生(除非你是故意使其越界),因为越界的结果要么是程序崩溃,要么是摧毁程序的堆、栈结构,产生以想不到的结果,就算是在你的程序运行过程中,没有发生上面的问题,你还是要小心,说不定什么时候就崩掉,那时候debug可是相当困难的。
追求执着 2011-10-19
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 lirunfa 的回复:]
另附:
自由存储区和堆不是一个概念。一般而言,自由存储区是指CRT(C运行时库)通过malloc,free函数管理的内存。堆特指通过new,delete管理的内存。但是在部分编译器的实现上这两块内存都是同一种管理方式。

C++ 里面也可以调用malloc和free操作。所以C++里面两种概念都存在的。在C里面可以理解就存在自由存储区这样一个概念。


引用 9 楼 zzcmx2008……
[/Quote]
3Q
lirunfa 2011-10-19
  • 打赏
  • 举报
回复
另附:
自由存储区和堆不是一个概念。一般而言,自由存储区是指CRT(C运行时库)通过malloc,free函数管理的内存。堆特指通过new,delete管理的内存。但是在部分编译器的实现上这两块内存都是同一种管理方式。

C++ 里面也可以调用malloc和free操作。所以C++里面两种概念都存在的。在C里面可以理解就存在自由存储区这样一个概念。

[Quote=引用 9 楼 zzcmx2008 的回复:]
栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区。里面的变量通常是局部变量、函数参数等。在一个进程中,位于用户虚拟地址空间顶部的是用户栈,编译器用它来实现函数的调用。和堆一样,用户栈在程序执行期间可以动态地扩展和收缩。

堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么……
[/Quote]
追求执着 2011-10-19
  • 打赏
  • 举报
回复

看来这个问题不值得探讨
阿霖 2011-10-18
  • 打赏
  • 举报
回复
学习 帮顶~
zzcmx2008 2011-10-18
  • 打赏
  • 举报
回复
呵呵,我一般就是记的最先发的那个,其他的感觉,都是自己维护自己开辟的内存就是了。
追求执着 2011-10-18
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 zzcmx2008 的回复:]
栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区。里面的变量通常是局部变量、函数参数等。在一个进程中,位于用户虚拟地址空间顶部的是用户栈,编译器用它来实现函数的调用。和堆一样,用户栈在程序执行期间可以动态地扩展和收缩。

堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么……
[/Quote]
谢谢,也是这个理解的
追求执着 2011-10-18
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 keiy 的回复:]
而最终link后的,BCB6将内存分了有8个段
# Name VirtSize RVA PhysSize Phys off Flags
-- -------- -------- -------- -------- -------- --------
01 .text 0000A000 00001000 00009400 00000600 60000020 [CER]
02 .data 00……
[/Quote]
恩,因编译器或者系统和而不同?
zzcmx2008 2011-10-18
  • 打赏
  • 举报
回复

栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区。里面的变量通常是局部变量、函数参数等。在一个进程中,位于用户虚拟地址空间顶部的是用户栈,编译器用它来实现函数的调用。和堆一样,用户栈在程序执行期间可以动态地扩展和收缩。

堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。堆可以动态地扩展和收缩。

自由存储区,就是那些由malloc等分配的内存块,他和堆是十分相似的,不过它是用free来结束自己的生命的。(应该是针对C语言来说的)

全局/静态存储区,全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的(初始化的全局变量和静态变量在一块区域,未初始化的全局变量与静态变量在相邻的另一块区域,同时未被初始化的对象存储区可以通过void*来访问和操纵,程序结束后由系统自行释放),在C++里面没有这个区分了,他们共同占用同一块内存区。

常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改(当然,你要通过非正当手段也可以修改,而且方法很多)

另附:
自由存储区和堆不是一个概念。一般而言,自由存储区是指CRT(C运行时库)通过malloc,free函数管理的内存。堆特指通过new,delete管理的内存。但是在部分编译器的实现上这两块内存都是同一种管理方式。

C++ 里面也可以调用malloc和free操作。所以C++里面两种概念都存在的。在C里面可以理解就存在自由存储区这样一个概念。
柯本 2011-10-18
  • 打赏
  • 举报
回复
而最终link后的,BCB6将内存分了有8个段
# Name VirtSize RVA PhysSize Phys off Flags
-- -------- -------- -------- -------- -------- --------
01 .text 0000A000 00001000 00009400 00000600 60000020 [CER]
02 .data 00003000 0000B000 00002600 00009A00 C0000040 [IRW]
03 .tls 00001000 0000E000 00000200 0000C000 C0000040 [IRW]
04 .rdata 00001000 0000F000 00000200 0000C200 50000040 [IRS]
05 .idata 00001000 00010000 00000600 0000C400 40000040 [IR]
06 .edata 00001000 00011000 00000200 0000CA00 40000040 [IR]
07 .rsrc 00001000 00012000 00000200 0000CC00 40000040 [IR]
08 .reloc 00001000 00013000 00000A00 0000CE00 50000040 [IRS]
而VC只分了3个
Object table:
# Name VirtSize RVA PhysSize Phys off Flags
-- -------- -------- -------- -------- -------- --------
01 .text 00004F58 00001000 00005000 00001000 60000020 [CER]
02 .rdata 0000124E 00006000 00002000 00006000 40000040 [IR]
03 .data 00001C88 00008000 00001000 00008000 C0000040 [IRW]
追求执着 2011-10-18
  • 打赏
  • 举报
回复

zzcmx2008 2011-10-18
  • 打赏
  • 举报
回复
其实是自己malloc或new的,自己记得释放就可以了
柯本 2011-10-18
  • 打赏
  • 举报
回复
这个,要看编译器的实现,不同编译器最终的实现是不同的
BCB6的
_TEXT segment dword public use32 'CODE'
_TEXT ends
_DATA segment dword public use32 'DATA'
_DATA ends
_BSS segment dword public use32 'BSS'
_BSS ends
DGROUP group _BSS,_DATA
_TEXT segment dword public use32 'CODE'
VC2003的
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
_DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA ENDS
CONST SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT DWORD USE32 PUBLIC 'BSS'
_BSS ENDS
$$SYMBOLS SEGMENT BYTE USE32 'DEBSYM'
$$SYMBOLS ENDS
_TLS SEGMENT DWORD USE32 PUBLIC 'TLS'
_TLS ENDS
FLAT GROUP _DATA, CONST, _BSS
ASSUME CS: FLAT, DS: FLAT, SS: FLAT
zzcmx2008 2011-10-18
  • 打赏
  • 举报
回复
这个是大家的说法不一样。记住第二和第三条,其他的都是第一条里面的。
追求执着 2011-10-18
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 zzcmx2008 的回复:]
借用《高质量C++编程指南》的一段,如下:
内存分配方式有三种:
(1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。
(2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
(3)……
[/Quote]
这段我看过,但是也有人将内存分为5个部分
栈---堆---自由存储区---静态存储区---常量存储区
zzcmx2008 2011-10-18
  • 打赏
  • 举报
回复
借用《高质量C++编程指南》的一段,如下:
内存分配方式有三种:
(1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。
(2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
(3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。

自由存储区通常应该指的是静态存储区域吧。
满月的愿望 2011-10-18
  • 打赏
  • 举报
回复
在c++内或许不同了,具体不了解

64,643

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧