PHP变量的内存管理

转载 2018年04月17日 17:41:32

每门计算机语言都需要一些容器来保存变量数据。在一些语言当中,变量都有特定的类型,如字符串,数组,对象等等。比如C和Pascal就属于这种。 而PHP则没有这样的类型。在PHP中,一个变量在某一行是字符串,可能到下一行就变成了数字。变量可以经常在不同的类型间轻易的转化,甚至是自动的转 换。PHP之所以成为一个简单并且强大的语言,很大一部分的原因是它拥有弱类型的变量。但是有些时候这也会带来一些有趣的问题。

在PHP内部,变量是存储在一个叫做zval的容器中。它不仅仅包含变量的值,也包含变量的类型。Python和PHP类似,也有一个标签标记变量类型。变量容器中包含一些Zend引擎用来区分是否引用的字段。同时它也包含这个值的引用计数。

变量存储在一个相当于关联数组的符号表中。这个数组以变量名为key,并且指向包含了这些变量的容器。如下图所示:


引用计数

PHP试着在变量拷贝(如 $a = $b )的时候变得聪明些。“=”也称为赋值操作符。当进行赋值操作时,Zend引擎不会创建一个新的变量窗口,而是增大变量窗口的 refcount 字段,你可以想象一下,当这个变量是一个巨大的字符串或一个巨大 的数组时,这将节约多少的内存。如下图所示:


第一步: 变量a,包含文本”this is”。默认情况下,引用计数等于1

第二步:将变量$a赋值给$b和$c。这里没有新的变量容器生成,仅仅是每次在变量赋值操作时将refcount加1。因为这里执行了两次赋值操作,所以refcount最后会变成3。

现在,也许你很想知道当变量$c改变时将发生什么。根据refcount的值的不同,它会有两种不同的处理方式。如果 refcount等于1,这个变量容器将更新它的值(也许同时会更新它的类型)。如果refcount大于1,将创建一个包含了新值(和类型)的变量容 器。如图2所示的第三步,$a变量所在的变量容器的refcount值被减去一,现在refcount的值是2,而新创建的容器的refcount的值为 1。当对一个变量使用unset函数时,这个变量所在的容器的refcount值将减去一,如图第4步所示。如果refcount的值少于1,Zend引 擎将翻译这个变量容器,如图第5步所示。

传递变量给函数(Passing Variables to Functions)

除了所有脚本共用的全局符号表以外,每个用户定义的函数在调用时都会创建一个属于自己的符号表,用来存放它自己的变量。当一个函数被调用后,Zend引擎 就会创建一个这样的符号表,当这个函数返回时这个函数表就会被释放。一个函数要么通过return语句返回,要么因为函数结束而返回(译者注:无返回的函 数默认会返回NULL)。如下图所示:


图3详细介绍了变量是如何传递给函数的。

第一步,我们将”thisis”赋给变量$a,然后我们将这个变量传递do_something()函数的$s变量。

第二步,你可以看到这与变量赋值的操作是一样的(与我们在前一小节提到的$b = $a类似),只是其存储在不同的符号表(函数符号表),并且引用计数加2,而不是加1。原因是函数栈也包含了这个变量容器的引用。

第三步,当我们赋新值给变量$s,原变量容器的refcount减1,并且创建一个包含了新值的变量容器。

第四步,我们通过return语句返回一个变量。返回的变量从全局符号表中获取一个实体并将其refcount的值增加1.当函数结束时,函数的符 号表将被销毁。在销毁的过程中,Zend引擎将遍历符号表中的每个变量,并将其refcount的值减少。当变量容器的refount的值变为0,这个变 量容器将会被销毁。如你所见,由于 PHP的引用计数机制,变量容器不是以拷贝的方式从函数返回。如果变量$s在第三步时没有被修改,则变量$a和$b将一直指向相同的变量容器(这个容器的 refcount为2)。在这种情况下,语句$a = “this is”将不会创建变量容器的副本。

Part 19:Cocos2d-x开发实战-Cocos2d-x中的内存管理

介绍了Cocos2d-x中的内存管理的必要性,在Cocos2d-x中内存管理比较麻烦的是Ref类和它的子类,它们采用了引用计数,create开头的静态构造函数可以避免内存管理代码的麻烦。如果使用其它数据类型如:Value、 Vector和Map我们可以不需要对它们进行内存管理。
  • 2016年04月12日 13:41

php垃圾回收和内存管理机制

一、PHP 垃圾回收机制(Garbage Collector 简称GC) 在PHP中,没有任何变量指向这个对象时,这个对象就成为垃圾。PHP会将其在内存中销毁;这是PHP的GC垃圾处理机制,防止内存...
  • Wss0130
  • Wss0130
  • 2016-04-01 11:07:39
  • 3428

php全局变量的内存管理

话不多说,code is the true。 第一段: class Globals{ public $var = array(); function __construct(){  glob...
  • chuiqihuangfeng2015
  • chuiqihuangfeng2015
  • 2016-03-14 16:03:11
  • 544

45-PHP的内存管理

45-PHP的内存管理内存管理一般会包括以下的内容: 是否有足够的内存供我们的程序使用; 如何从足够可用的内存中获取部分内存; 对于使用后的内存,是否可以将其销毁并将其重新分配给其它程序使用。 与此对...
  • ghostlv
  • ghostlv
  • 2016-04-26 12:22:24
  • 953

内存管理基本原则

之前:OC内存管理遵循“谁创建,谁释放,谁引用,谁管理”的机制,当创建或引用一个对象的时候,需要向她发送alloc、copy、retain消息,当释放该对象时需要发送release消息,当对象引用计数...
  • u012701023
  • u012701023
  • 2016-03-24 15:41:27
  • 887

PHP内核--探究内存管理与缓存机制

PHP的内存管理可以被看作是分层(hierarchical)的。 它分为三层:存储层(storage)、堆层(heap)和接口层(emalloc/efree)。 存储层通过 malloc()、mmap...
  • ty_hf
  • ty_hf
  • 2016-10-23 23:39:50
  • 2713

Block的内存管理以及变量Capture

总的来说,Block = 匿名函数 + Capture变量。它的用途包括: 作为匿名函数使用,即把函数定义在使用到的地方,逻辑更加集中。 Capture变量,可以capture Block定义所在的作...
  • fly1183989782
  • fly1183989782
  • 2017-05-07 13:53:15
  • 217

iOS-Block和变量的内存管理(二)

了解了 block的实现,我们接着来聊聊 block 和变量的内存管理。本文将介绍 可写变量 block的内存段 __block变量的内存段等内容 看完本文会对 block 和...
  • zhz459880251
  • zhz459880251
  • 2016-03-13 16:52:23
  • 577

IOS开发—block对外部变量的内存管理

代码块在ios中通常用于回调,本文主要介绍block对外部变量的管理机制。我们知道如果要在block中使用block外面的变量,如果该变量是局部变量,就要先将其申明为__block类型。为什么呢?这就...
  • Lotheve
  • Lotheve
  • 2015-03-21 14:18:29
  • 2846

php扩展之(zend内存管理及zend引擎)

前面一篇写了如何生成扩展模块及书写一个简单d扩展模块,当设计到用c书写复杂的扩展函数那么就离不开zend 内存篇了;本文整理内存管理相关内容; 内存管理   在C语言里,分配内...
  • fengye245
  • fengye245
  • 2012-08-16 13:59:52
  • 1974
收藏助手
不良信息举报
您举报文章:PHP变量的内存管理
举报原因:
原因补充:

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