Guru of the Week 条款09:内存管理(上篇)

原创 2001年10月23日 20:17:00
 

GotW #09 Memory Management - Part I

著者:Herb Sutter     

翻译:kingofark

[声明]:本文内容取自www.gotw.ca网站上的Guru of the Week栏目,其著作权归原著者本人所有。译者kingofark在未经原著者本人同意的情况下翻译本文。本翻译内容仅供自学和参考用,请所有阅读过本文的人不要擅自转载、传播本翻译内容;下载本翻译内容的人请在阅读浏览后,立即删除其备份。译者kingofark对违反上述两条原则的人不负任何责任。特此声明。

Revision 1.0

Guru of the Week 条款09:内存管理(上篇)<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

难度:3 / 10

 

(本条款介绍C++中几个主要内存区域的基本知识。条款10将会继续本条款的话题,深入讨论一些内存管理的问题。)

 

 

[问题]

 

C++拥有几个不同的内存区域,用来存储对象或其它类型的值。每一个区域都有其各自的特点。

 

请叫出尽可能多的内存区域的名称,并分析每一个区域的性能特征,描述存储在其中的对象的生存周期。

 

举例:堆栈区(stack)存储自动变量(automatic variables),包括内建类型和类对象等。

 

 

[解答]

 

下面总结出了C++程序主要的内存区域。注意,有些名称(比如heap)可能与C++标准中的叫法不一样。

[常量数据(const data)区:]

 常量数据区存储字符串等在编译期间就能确定的值。类对象不能存在于这个区域中。在程序的整个生存周期内,区域中的数据都是可用的。

   区域内所有的数据都是只读的,任何企图修改本区域数据的行为都会造成无法预料的后果。之所以会如此,是因为在实际的实现当中,即使是最底层的内部存储格式也受制于所实现的特定的优化方案。例如,一种编译器完全可以把字符串存放在几个重叠的对象里面——只要实现者愿意的话。  

[栈(stack)区:]

   栈区存储自动变量(automatic variables)。一般来说,栈区的分配操作要比动态存储区(比如堆(heap)或者自由存储区(free store))快得多,这是因为栈区的分配只涉及到一个指针的递增,而动态存储区的分配涉及到较为复杂的管理机制。栈区中,内存一旦被分配,对象就立即被构造好了;对象一旦被销毁,分配的内存也立即被收回(译注:这里作者用了“去配(deallocate)”一词,鄙人一律翻译为“回收”)。因此,在栈区中,程序员没有办法直接操纵那些已经被分配但还没有被初始化的栈空间(当然,那些通过使用显式(explicit)析构函数(destructor)和new运算符而故意这么做的情况不算在内)。

[自由存储区(free store):]

   自由存储区(free store)是C++两个动态内存区域之一,使用newdelete来予以分配和释放(freed)。在自由存储区(free store)中,对象的生存周期可以比存放它的内存区的生存周期短;这也就是说,我们可以获得一片内存区而不用马上对其进行初始化;同时,在对象被销毁之后,也不用马上收回其占用的内存区。在对象被销毁而其占用的内存区还未被收回的这段时间内,我们可以通过void*型的指针访问这片区域,但是其原始对象的非静态成员以及成员函数(即使我们知道了它们的地址)都不能被访问或者操纵。

[堆(heap)区:]

    堆(heap)区是另一个动态存储区域,使用mallocfree以及一些相关变量来进行分配和回收。要注意,虽然在特定的编译器里缺省的全局运算符newdelete也许会按照mallocfree的方式来被实现,但是堆(heap)与自由存储区(free store)是不同的——在某一个区域内被分配的内存不可能在另一个区域内被安全的回收。堆heap中被分配的内存一般用于存放在使用new的构造过程中和显式(explicit)的析构过程中涉及到的类对象。堆中对象的生存周期与自由存储区(free store)中的类似。

[全局/静态区(Global/Static):]

   全局的或静态的变量和对象所占用的内存区域在程序启动(startup)的时候才被分配,而且可能直到程序开始执行的时候才被初始化。比如,函数中的静态变量就是在程序第一次执行到定义该变量的代码时才被初始化的。对那些跨越了翻译单元(translation unit)的全局变量进行初始化操作的顺序是没有被明确定义的,因而需要特别注意管理全局对象(包括静态类对象)之间的依赖关系。最后,和前面讲的一样,全局/静态区(Global/Static)中没有被初始化的对象存储区域可以通过void*来被访问和操纵,但是只要是在对象真正的生存周期之外,非静态成员和成员函数是无法被使用或者引用的。

[关于“堆(heapvs.自由存储区(free store)”]:本条款中我们将堆(heap)和自由存储区(free store)区分开来,是因为在C++标准草案中,关于这两种区域是否有联系的问题一直很谨慎的没有予以详细说明。比如当内存在通过delete运算符进行回收时,18.4.1.1中说道:

 

It is unspecified under what conditions part or all of such reclaimed storage is allocated by a subsequent call to operator new or any of calloc, malloc, or realloc, declared in <cstdlib>.

[关于在何种情况下,这种内存区域的部分或全部才会通过后续的对new(或者是在<cstdlib>里声明的callocmallocrealloc中的任何一个)的调用来被分配的问题,在此不作详细规定,不予详述。]

 

同样,在一个特定的实现中,到底newdelete是按照mallocfree来实现的,或者反过来mallocfree是按照newdelete来实现的,这也没有定论。简单地说吧,这两种内存区域运作方式不一样,访问方式也不一样——所以嘛,当然应该被当成不一样的两个东西来使用了!

安装Oracle 11g r2先决条件检查失败解决方法

安装Oracle 11g r2先决条件检查失败解决方法 收藏到手机  转发   评论 2012-03-28 10:43    //物理内存 物理内存 - 此先决条件将测试系统物理内存总量是否至少...
  • haiross
  • haiross
  • 2013年10月14日 13:54
  • 61989

内存堆管理器GenCollectedHeap的初始化

前文在介绍Java对象内存分配的上层接口CollectedHeap时就提过, GenCollectedHeap是一种基于内存分代管理的内存堆管理器实现. 它一方面负责java对象的内存分配, 另一方面...
  • xhh198781
  • xhh198781
  • 2014年11月16日 17:17
  • 2363

LwIP之内存管理和配置

LwIP中的内存管理      LwIP中的有两种方式的内存,heap和pool。老衲五木的《LwIP协议栈源码详解》将heap称之为动态内存堆,将pool称为动态内存池。      heap像是...
  • wjjontheway
  • wjjontheway
  • 2013年06月13日 22:12
  • 2607

cheshire cat/pimpl idiom & Guru of the Week 条款28:“Fast Pimpl”技术

PIMPL是C++开发中经常使用的一种惯用法,其原理主要是将对定义的依赖转换为对声明的依赖,通过前向声明,达到接口与实现的分离的效果,并将编译时文件间的依赖降到最低,从而大大缩短程序编译的时间。 P...
  • tianalotus
  • tianalotus
  • 2013年06月21日 17:41
  • 701

C++必知必会-----条款36 特定于类的内存管理

1、我们无法对new操作符和delete操作符做什么,因为它们的行为是固定的,但是可以改变它们所调用的operator new和operator delete。 2、实现方式就是在类中定义ope...
  • qdqht2009
  • qdqht2009
  • 2014年03月11日 10:28
  • 446

IOS开发基础Object-C(09)—OC内存管理(3)-@property的参数详解

在 IOS开发基础Object-C(06)—@property 和@synthesize语法中我们已经大体了解了@property的参数,今天我们就来详细解释一下@property关于内存管理的用法。...
  • u010037928
  • u010037928
  • 2015年11月23日 19:35
  • 1681

The Book of QT4 翻译:1.2 布局,对象层级和内存管理

The Book of QT4 翻译:1.2 布局,对象层级和内存管理 作者:mcxiaoke  来源:博客园  发布时间:2010-05-12 10:57  阅读:651 次  原文链接 ...
  • hqyhqyhq
  • hqyhqyhq
  • 2012年06月27日 14:37
  • 745

给Unity开发者的C#内存管理(第二部分) C# Memory Management for Unity Developers (part 2 of 3)

【三部曲中的第一篇文章讨论了.NET/Mono以及Unity中的内存管理的基础,并且提供了一些避免不必要的堆内存分配的小提示。第三篇则讲了对象池。所有的内容都是面向“中级”C#开发者】 现在,来仔细...
  • IceCracker
  • IceCracker
  • 2016年10月11日 14:04
  • 445

Sun JDK 1.6内存管理--调优篇-毕玄

  • 2012年11月29日 17:17
  • 522KB
  • 下载

终极图解内存(上篇)

  • 2013年01月14日 21:46
  • 1.77MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Guru of the Week 条款09:内存管理(上篇)
举报原因:
原因补充:

(最多只允许输入30个字)