【问题标题】:How are PHP static variables implemented internally?PHP 静态变量是如何在内部实现的?
【发布时间】:2014-02-17 14:27:12
【问题描述】:

我希望 xdebug 有朝一日能够浏览所有静态变量和属性,但根据作者的说法,无法在引擎中获得这些的列表。这让我感到惊讶,因为静态变量看起来就像具有孤立范围的全局变量。

它们真的没有存储在哈希表中,还是表条目不可枚举的问题?

【问题讨论】:

  • 我很确定你最好询问 Derick Rethans(XDebug 的作者和 PHP 语言 / Zend 引擎的活跃开发人员)或在 php 内部列表 (internals@lists. php.net)
  • 我认为将它们视为全局变量是一种狭隘的观点。您可以在函数中有一个静态变量,它只会被初始化一次。否则,它就像任何其他变量一样。
  • @BrentBaisley 请注意,除了静态允许使用快捷方式初始化器之外,它们的行为相同:3v4l.org/68uRA
  • 这更令人惊讶:3v4l.org/JTc71 "static" 为您提供了一个内部值,但您可以将其从当前范围解除绑定,重用本地变量,然后再次重新绑定。跨度>

标签: php c compiler-construction static


【解决方案1】:

PHP 函数内部可以有两种类型:内部函数或用户定义函数。内部函数是用 C 语言编写的,可以做“任何事情”。用户定义的函数由带有元数据的“oparray”表示。 oparray 包含 PHP/ZE 字节码形式的函数表达式。 oparray 的一个元素包含一个包含所有静态变量的表。

因此,为了获取所有静态变量,必须遍历所有用户定义的函数(以及所有类中的类方法)并检查该数组。

对于全局函数,这个未经测试的 C 代码可能会起作用:

int dump_statics(zend_function *function TSRMLS_DC)
{
    if (function->type == ZEND_USER_FUNCTION) {
        ulong    hashIndex    = 0;
        char*    hashKey      = NULL;
        int      hashKeyType  = 0;
        zend_hash_internal_pointer_reset(function->op_array.static_variables);
        while ((hashKeyType = zend_hash_get_current_key(function->op_array.static_variables, &hashKey, &hashIndex, 0)) {
            if (hashKeyType == HASH_KEY_IS_STRING) {
                php_printf("%s\n", hashkey);
            }
            zend_hash_move_forward(function->op_array.static_variables);
        }
    }
    return 0;
}
zend_hash_apply(EG(function_table), (apply_func_t) dump_statics TSRMLS_CC);

对于类方法,必须遍历 EG(class_table),然后是包含的类条目的 funtion_table ... 作为练习留给读者。 (就像测试上面的代码一样)


更新:

我为此创建了一个简单的 PHP 扩展。可以从https://github.com/johannes/php-staticvardumper获得它

【讨论】:

  • 我假设您的意思是“因此,为了获得所有静态 变量,必须迭代...”
  • 所以我假设hashKey 引用了某种全局可访问的表?而xdebug,为了保持快速,可能需要一个大链表中的所有这些哈希键?只是好奇:全局变量是否存储在同一张表中?
  • zend_hash_apply 是作用于函数表的外部迭代器。在那里,zend_hash_* 函数对静态变量表进行内部迭代。 hashKey 是一个局部变量,它检索键(-> 变量名)
  • 哦,所以hashKey实际上是变量名(没有$)?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-19
  • 1970-01-01
  • 1970-01-01
  • 2021-11-02
  • 2016-07-26
  • 1970-01-01
相关资源
最近更新 更多