【问题标题】:Where is the source code for strlen() function in PHP?PHP中strlen()函数的源代码在哪里?
【发布时间】:2020-05-24 19:23:05
【问题描述】:

我浏览了php-src/Zend/zend_API.c,但在任何地方都找不到PHP 中strlen() 函数的源代码。浏览代码库并没有真正的帮助,因为它到处都是 libc strlen。谷歌搜索也没有多大帮助。

我尝试使用 Vulcan Logic Dumper 扩展来检查引擎盖下发生了什么。

我尝试了以下代码作为测试:

<?php

strlen("foo"); strpos("foo", "f");

这是我得到的:

寻找切入点 从位置进行分支分析:0 找到 1 个跳转。 (代码 = 62)位置 1 = -2 文件名:/tmp/test.php 函数名:(空) 操作数:7 编译的变量:无 line #* E I O op fetch ext 返回操作数 -------------------------------------------------- ---------------------------------- 3 0 E > 回声 3 4 1 INIT_FCALL 'strpos' 2 SEND_VAL“富” 3 SEND_VAL 'o' 4 DO_ICALL $0 5 回声 $0 6 > 返回 1

注意strpos() 如何显示为函数调用,而不是strlen()。所以我尝试了这个(这个在 PHP 7.4 上,顺便说一下)作为一个实验并且得到了一些有趣的东西。

代码

<?php
$str = "foo";

echo strlen($str);
echo strpos($str, "o");

Vulcan 的输出

寻找切入点 从位置进行分支分析:0 找到 1 个跳转。 (代码 = 62)位置 1 = -2 文件名:/tmp/test2.php 函数名:(空) 操作数:9 编译后的变量:!0 = $str line #* E I O op fetch ext 返回操作数 -------------------------------------------------- ---------------------------------- 2 0 E > 分配!0,'foo' 4 1 STRLEN ~2 !0 2 回声 ~2 5 3 INIT_FCALL 'strpos' 4 发送_VAR !0 5 SEND_VAL 'o' 6 DO_ICALL $3 7 回声 $3 8 > 返回 1

注意STRLEN 突然出现在操作列表中,但奇怪的是strpos() 显示为INIT_FCALLstrlen() 似乎与其他功能有所不同。我尝试了looking through the manual to better understand how the opcodes 的工作,但由于没有太多有用的信息而陷入死胡同。


谁能解释为什么strlen() 的行为似乎与其他函数如此不同,并可能指向我的源代码?也许我似乎无法找到它的来源的原因可能与它为什么如此特别有关?我不确定。

【问题讨论】:

标签: php strlen php-internals


【解决方案1】:

strlen() 实际上是 PHP 7 中的操作码,因此其行为不像典型函数。它的源代码位于第 53 行的php-src/Zend/zend_string.h(截至撰写本文时),它被定义为一个宏。

#define ZSTR_LEN(zstr)  (zstr)->len

基本上就是读取_zend_string structlen成员,它把字符串的长度存储为成员。

如果您查看 git-blame,您会发现该特定宏是在 2015 年 PHP 7 发布时添加的。

这是提交:https://github.com/php/php-src/commit/4bd22cf1c1d6a262fe2f026e082f2565433c53df

这是我的 git 日志所说的:

提交 4bd22cf1c1d6a262fe2f026e082f2565433c53df 作者:德米特里·斯托戈夫 日期:2015 年 6 月 29 日星期一 16:44:54 +0300 改进的 zend_string API (Francois Laupretre) 压缩提交以下内容: 提交 d96eab8d79b75ac83d49d49ae4665f948d15a804 作者:弗朗索瓦·洛普雷特 日期:2015 年 6 月 26 日星期五 01:23:31 +0200 在其余代码中使用新的“ZSTR”宏。 不会对生成的代码进行任何更改(感谢兼容宏),但更简洁。 提交 b3526439104ac7a89a8e0c79dbebf33b22bd01b8 作者:弗朗索瓦·洛普雷特 日期:2015 年 6 月 25 日星期四 13:45:06 +0200 改进 zend_string API 添加缺少的方法

所以看起来在 PHP 7 发布的某个时候,对 API 进行了一些改进。尚不清楚这是否意味着 strlen() 从一个函数变成了一个操作码,或者它是否一直是一个操作码。

不过,我确实看到了 interned string 东西可能会如何影响实验中 Vulcan 的输出。如果您使用内部字符串,PHP 似乎出于某种原因在执行程序中采用了某种捷径。我不清楚具体是怎么做的,但是是的,它的行为似乎与典型的函数有些不同。

【讨论】:

  • 谢谢!你不会相信我花了多少时间挖掘这个源代码来试图弄清楚strlen 是如何工作的,哈哈。你是个巫师!
  • 没问题! PHP 的源代码有时肯定会令人困惑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多