目录
What Is a zval?
How PHP Handles Type Changes
Reference Counting and Copy-on-Write
References vs. Variables
Garbage Collection and Circular References
Summary of Key Points
首页 后端开发 php教程 变量的寿命:PHP的内部' Zval”结构解释了

变量的寿命:PHP的内部' Zval”结构解释了

Jul 27, 2025 am 03:47 AM
PHP Data Types

PHP使用zval结构管理变量,答案是:1. zval包含值、类型和元数据,大小为16字节;2. 类型变化时只需更新联合体和类型信息;3. 复杂类型通过指针引用带引用计数的结构;4. 赋值时采用写时复制优化内存;5. 引用使变量共享同一zval;6. 循环引用由专门的垃圾回收器处理。这解释了PHP变量行为的底层机制。

The Life of a Variable: PHP\'s Internal `zval` Structure Explained

When you write PHP code like:

The Life of a Variable: PHP's Internal `zval` Structure Explained
$foo = 42;
$foo = "hello";
$foo = [];

It feels natural — after all, PHP is a dynamically typed language. But under the hood, PHP has to manage a lot more complexity than it lets on. Every variable you create isn’t just a simple value; it’s a sophisticated structure managed by the Zend Engine. That structure is called a zval.

Understanding the zval is key to understanding how PHP handles variables, memory, and type juggling internally.

The Life of a Variable: PHP's Internal `zval` Structure Explained

What Is a zval?

A zval (short for "Zend value") is the fundamental data structure PHP uses to represent a variable. It doesn’t just store the value — it stores the value, the type, memory management info, and other metadata.

As of PHP 7 (and continuing in PHP 8), the zval structure was overhauled for performance and memory efficiency. Here’s a simplified version of what it looks like internally:

The Life of a Variable: PHP's Internal `zval` Structure Explained
struct _zval_struct {
    zend_value value;        // The actual value (long, double, string, etc.)
    union {
        uint32_t type_info;  // Combined type and flags
    } u1;
    union {
        uint32_t next;       // Used in arrays (bucket index)
    } u2;
};

The zend_value union can hold different types:

typedef union _zend_value {
    zend_long         lval;    // integer
    double            dval;    // float
    zend_refcounted  *counted; // strings, arrays, objects
    zend_string      *str;     // string
    zend_array       *arr;     // array
    zend_object      *obj;     // object
    zend_resource    *res;     // resource
    zend_reference   *ref;     // reference
} zend_value;

So a zval doesn’t directly contain a string or array — it contains a pointer to a more complex structure that holds the actual data and metadata like reference counts.


How PHP Handles Type Changes

Let’s go back to our example:

$foo = 42;
$foo = "hello";

In PHP 5, each variable was a separate structure (zval refcount is_ref), and changing types required careful cleanup and reallocation.

In PHP 7 , the zval is small (16 bytes on 64-bit systems) and is often allocated inline. When you assign an integer:

$foo = 42;

The zval stores:

  • value.lval = 42
  • type_info = IS_LONG

Then you reassign:

$foo = "hello";

PHP simply:

  1. Clears the old type
  2. Sets value.str = pointer to zend_string("hello")
  3. Updates type_info = IS_STRING

No need to free the entire zval — just update its union and type. This makes variable reuse fast.


Reference Counting and Copy-on-Write

PHP uses reference counting and copy-on-write to save memory.

Example:

$a = [1, 2, 3];
$b = $a; // Not copied yet — just referenced
$b[] = 4; // Now it's copied!

Here’s what happens:

  1. $a points to a zend_array with refcount = 1.
  2. $b = $a → refcount becomes 2. No data is duplicated.
  3. When you modify $b, PHP sees refcount > 1, so it copies the array before changing it (copy-on-write).
  4. Refcount for original drops, new array gets refcount = 1.

This is all tracked inside the zend_refcounted header, which is embedded in strings, arrays, objects, etc.

struct _zend_refcounted_h {
    uint32_t refcount;
    union {
        struct {
            uint32_t type_info;
        } v;
    } u;
};

So when a zval holds a string or array, its value.counted points to a structure that includes this header.


References vs. Variables

You might think & means "make a reference," but internally, it changes how the zval is treated.

$a = 42;
$b = &$a;
$b = 100;

Now both $a and $b point to the same zval. This is different from normal assignment, which would create a new zval.

Internally, the engine marks the zval as being under reference (via ZEND_TYPE_REFCOUNTED and flags), and disables copy-on-write. Any change affects all referencing variables.


Garbage Collection and Circular References

Reference counting works well — until you have cycles:

$a = [];
$b = [];
$a['b'] = $b;
$b['a'] = $a;

Now $a and $b reference each other. Even if you unset both, their internal refcounts don’t hit zero.

PHP uses a separate garbage collector to detect and clean such cycles. It kicks in when:

  • A refcounted variable is unset
  • But its refcount doesn’t drop to zero
  • And it might be part of a cycle

The GC periodically scans for such "possible root cycles" and frees them if confirmed.


Summary of Key Points

  • A zval is the core structure representing a PHP variable.
  • It stores a union (zend_value) and type info in 16 bytes.
  • Types can change efficiently — just update the union and type.
  • Complex types (string, array) are stored separately with reference counting.
  • Copy-on-write delays duplication until necessary.
  • References (&) make variables share the same zval.
  • Circular references are handled by a dedicated garbage collector.

Understanding zval doesn’t just satisfy curiosity — it helps explain why certain PHP behaviors exist, like why assigning large arrays isn’t expensive until you modify them, or why circular references can cause memory leaks if not handled.

It’s the quiet engine behind PHP’s ease of use.

Basically, every time you write $var = ..., you’re working with a zval — even if you never see it.

以上是变量的寿命:PHP的内部' Zval”结构解释了的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Stock Market GPT

Stock Market GPT

人工智能驱动投资研究,做出更明智的决策

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

使用PHP 8的工会类型对您的代码库进行现代化现代化 使用PHP 8的工会类型对您的代码库进行现代化现代化 Jul 27, 2025 am 04:33 AM

UpgradePHP7.xcodebasestoPHP8 byreplacingPHPDoc-suggestedtypeslike@paramstring|intwithnativeuniontypessuchasstring|intforparametersandreturntypes,whichimprovestypesafetyandclarity;2.Applyuniontypestomixedinputparameters(e.g.,int|stringforIDs),nullable

PHP 8.1枚举:一种新型类型安全常数的范式 PHP 8.1枚举:一种新型类型安全常数的范式 Jul 28, 2025 am 04:43 AM

PHP8.1引入的Enums提供了类型安全的常量集合,解决了魔法值问题;1.使用enum定义固定常量,如Status::Draft,确保只有预定义值可用;2.通过BackedEnums将枚举绑定到字符串或整数,支持from()和tryFrom()在标量与枚举间转换;3.枚举可定义方法和行为,如color()和isEditable(),增强业务逻辑封装;4.适用于状态、配置等静态场景,不适用于动态数据;5.可实现UnitEnum或BackedEnum接口进行类型约束,提升代码健壮性和IDE支持,是

精度的危险:处理PHP中的浮点数 精度的危险:处理PHP中的浮点数 Jul 26, 2025 am 09:41 AM

0.1 0.2!==0.3inPHPduetobinaryfloating-pointprecisionlimitations,sodevelopersmustavoiddirectcomparisonsanduseepsilon-basedchecks,employBCMathorGMPforexactarithmetic,storecurrencyinintegerswhenpossible,formatoutputcarefully,andneverrelyonfloatprecision

从'混合到`void':php返回类型声明的实用指南 从'混合到`void':php返回类型声明的实用指南 Jul 27, 2025 am 12:11 AM

returnTypesinphpimProveCoderEliabilitialaryandClarityBysPecifying whatafunctionMustReturn.2.UseBasictyPesLikestring,array,ordatimetoetoEnforCorrectRecturcrectRecturnValuesUnturnvAluesAndCatchErrorSearly.3.applynullabletypespeswith?applynullabletypeswith?

变量的寿命:PHP的内部' Zval”结构解释了 变量的寿命:PHP的内部' Zval”结构解释了 Jul 27, 2025 am 03:47 AM

PHP使用zval结构管理变量,答案是:1.zval包含值、类型和元数据,大小为16字节;2.类型变化时只需更新联合体和类型信息;3.复杂类型通过指针引用带引用计数的结构;4.赋值时采用写时复制优化内存;5.引用使变量共享同一zval;6.循环引用由专门的垃圾回收器处理。这解释了PHP变量行为的底层机制。

PHP中的资源管理:'资源”类型的生命周期 PHP中的资源管理:'资源”类型的生命周期 Jul 27, 2025 am 04:30 AM

PHP资源的生命周期分为三个阶段:1.资源创建,通过fopen、curl_init等函数获取外部系统句柄;2.资源使用,将资源传递给相关函数进行操作,PHP通过资源ID映射到底层系统结构;3.资源销毁,应优先手动调用fclose、curl_close等函数释放资源,避免依赖自动垃圾回收,以防文件描述符耗尽。最佳实践包括:始终显式关闭资源、使用try...finally确保清理、优先选用支持__destruct的PDO等对象封装、避免全局存储资源,并可通过get_resources()监控活动资源

PHP的二元性:导航松散键入与严格类型声明 PHP的二元性:导航松散键入与严格类型声明 Jul 26, 2025 am 09:42 AM

PHP支持松散类型和严格类型并存,这是其从脚本语言演进为现代编程语言的核心特征。1.松散类型适合快速原型开发、处理动态用户输入或对接外部API,但存在类型隐式转换风险、调试困难和工具支持弱的问题。2.严格类型通过declare(strict_types=1)启用,可提前发现错误、提升代码可读性和IDE支持,适用于核心业务逻辑、团队协作和对数据完整性要求高的场景。3.实际开发中应混合使用:默认启用严格类型,仅在必要时在输入边界使用松散类型,并尽早进行验证和类型转换。4.推荐实践包括使用PHPSta

``?''的力量:有效利用PHP中的无效类型 ``?''的力量:有效利用PHP中的无效类型 Aug 08, 2025 am 01:50 AM

?在PHP中表示类型可为空,能提升代码的类型安全性和可读性;1.用于可选参数时确保传入值为指定类型或null;2.用于可能查找不到结果的返回值,明确告知调用者可能返回null;3.用于API等存在可选数据的场景,准确建模数据结构;使用时应仅在null有意义时使用,避免与默认null重复定义,结合??和?->操作符处理null值,并注意不可用于void类型,PHP8后?string与string|null等价但前者更简洁,合理使用可显着减少运行时错误。

See all articles