站长资讯网
最全最丰富的资讯网站

php的字符串管理 zend_string

php的字符串管理 zend_string

字符串管理:zend_string

任何程序都需要管理字符串。在这里,我们将详细介绍适合 PHP 需求的自定义解决方案:zend_string。每次 PHP 需要使用字符串时,都会使用 zend_string 结构。该结构仅仅是 C 语言的 char * 字符串类型的简单精简包装。

它添加了内存管理的功能,所以同一字符串可以在多个地方共享,而无需重复。另外,一些字符串是“内部的”,即“持久的”分配,并通过内存管理特殊管理,以便它们不会在多个请求中被销毁。之后,那些从Zend 内存管理获得永久分配。

相关学习推荐:PHP编程从入门到精通

结构和访问宏

这里是简单的zend_string结构:

struct _zend_string {         zend_refcounted_h gc;         zend_ulong        h;         size_t            len;         char              val[1]; };

如你所见,该结构嵌入了一个 zend_refcounted_h 标头。这个是内存管理和引用需要用到的。 由于该字符串很有可能作为哈希表检查的关键字,因此它在 h字段中嵌入了其哈希值。这是无符号长整型 zend_ulong。仅在需要对 zend_string 进行哈希处理时会用到,特别是和哈希表:zend_array一起用时。这很有可能。

如你所知,字符串知道其长度为 len 字段,以支持“二进制字符串。二进制字符串是嵌入一个或多个 NUL 字符()的字符串。当传递给库函数,那些字符串会被截断,否则无法正确计算其长度。所以在 zend_string 中,字符串的长度总是已知的。请注意,该长度计算的 ASCII 字符(字节),不计算最后的NUL,而是计算最终的中间的 NUL。例如,字符串 “foo” 在 zend_string 中存储为 “foo”,且它的长度为3。另外,字符串 “foobar” 将存储为 “foobar”,且其长度为7。

最终,该字符存储在 char[1]。这不是 char *,而是 char[1]。为什么?这是一种称为 “C struct hack” 的内存优化(你可以使用带有这些术语的搜索引擎)。基本上,它允许引擎为 zend_string 结构和要存储的字符分配空间,作为一个单独的 C 指针。这优化了内存,因为内存访问将是一个连续分配的块,而不是两个分散的块(一个用于存储 zend_string *,另一个用于存储 char *)。

必须记住这种 struct hack,由于内存布局看起来像 C 字符位于 C zend_string 结构的末尾,因此当使用 C 调试器(或调试字符串)时可能会感觉到/看到过。该 hack 是完全由 API 管理,当你操作 zend_string结构时会用到。

php的字符串管理 zend_string

使用 zend_string API

简单用例

像 Zvals,你不需要手动操作 zend_string 内部字段,而总是为此使用宏。还存在触发字符串操作的宏。这并不是函数,而是宏,都存储在必需的 Zend/zend_string.h 头文件:

zend_string *str;  str = zend_string_init("foo", strlen("foo"), 0); php_printf("This is my string: %sn", ZSTR_VAL(str)); php_printf("It is %zd char longn", ZSTR_LEN(str));  zend_string_release(str);

上面简单的例子为你展示了基本的字符串管理。应该为 zend_string_init() 函数(实际上是宏,但先让我们忽略它)给出完整的 char * C 字符串和它的长度。类型为 int 的最后一个参数应该为 0 或 1。如果传递0,则要求引擎通过 Zend 内存管理使用请求绑定的堆分配。这种分配在当前请求结束后时销毁。如果你不这么做,则在调试版本中,引擎会提醒你内存泄漏。如果传递1,则要求了所谓的“持久”分配,引擎将使用传统的 C malloc() 调用,并且不会以任何方式追踪内存分配。

注意

如果你需要

赞(0)
分享到: 更多 (0)
网站地图   沪ICP备18035694号-2    沪公网安备31011702889846号