PHP*_*Fan 10 php string php-internals
我正在使用Windows 10 Home Single Language Edition,它是我机器上的64位操作系统.
我安装了最新版本的XAMPP,它在我的机器上安装了PHP 7.2.7.
我根据PHP手册中的摘录问这个问题:
PHP中的字符串实现为字节数组和表示缓冲区长度的整数.它没有关于这些字节如何转换为字符的信息,将该任务留给程序员.字符串可以组成的值没有限制; 特别是,字符串中的任何地方都允许使用值为0的字节("NUL字节")(但是,本手册中称为"二进制安全"的一些函数)可能会将字符串移交给忽略数据后的数据库. NUL字节.)
我非常理解PHP中二进制安全函数和非二进制安全函数之间的区别.我心中怀疑.请以一对一的方式回答它们,并附上适当的解释和适当的例子.
像arkascha解释的那样,"二元安全"和"非二元安全"问题与语言无关.
使用空字节(0x00)来表示字符串的结尾更简单(这可能就是C随之而来的原因),但缺点是你不能在字符串中的任何地方都有一个空字节,这是一个很大的限制,如果你必须能够处理各种数据.将长度存储为字符串的元数据部分更复杂,如Pete所示,但它允许您处理任何类型的数据.
关于哪些函数是"二进制安全"或"非二进制安全",请在使用函数之前阅读PHP手册.我就是做这个的.不需要构建列表,因为PHP手册已经解释了您需要了解的有关函数的内容,包括它们是否是二进制安全的.
我相信,你的大多数帖子都是由于误解了你引用的PHP手册的解释,特别是这一部分:
但是,在本手册中称为"二进制安全"的一些函数可能会将字符串移交给在NUL字节后忽略数据的库.
让我尝试通过添加一些我自己的话来更清楚:
但是,在本手册中称为"二进制安全"的一些函数是可以将字符串移交给在NUL字节之后忽略数据的库的函数.
所以它真的没有说"非二进制安全函数将字符串移交给库",这是一种误解.这意味着"可以将字符串移交给在NUL字节后忽略数据的库的函数,在本手册中称为非二进制安全".
"移交给图书馆"只是说"从其他图书馆调用功能"的另一种方式."忽略NUL字节后的数据"是一种被称为非二进制安全的行为.
另一种方式是:
本手册中的一些函数被称为"二进制安全",因为它们可能调用其他也不是"二进制安全"的函数(在NUL字节之后忽略数据的函数).
我希望这能为你解决这个问题.
传统上有两种表示字符串的方法:通过使用特殊字符发信号通知字符串的结尾,或者将其长度与字符串数据一起存储.C使用前者; 字符串是一个char数组,末尾有一个空字符.但是,这有一个限制,即C中的字符串不能在其他地方使用空字符,而是在最后.
为克服此限制,PHP引擎使用此结构来表示字符串:
struct _zend_string {
zend_refcounted_h gc; /* refcount struct */
zend_ulong h; /* hash value */
size_t len; /* length of string */
char val[1]; /* array of chars (using struct "hack") */
};
Run Code Online (Sandbox Code Playgroud)
如您所见,PHP开发人员选择存储字符串的长度及其数据.
现在如果混合"二进制安全"和"非二进制安全"功能会发生什么?
考虑编写PHP扩展时可能使用的以下C代码:
zend_string *a = zend_string_init("a\0b", /* string length */ 3, 0);
zend_string *b = zend_string_init("a\0c", /* string length */ 3, 0);
if (strcmp(a->val, b->val) == 0) {
php_printf("Strings are equal!");
}
Run Code Online (Sandbox Code Playgroud)
你认为会发生什么?此代码输出"字符串相等!" 虽然他们显然不平等.由于strcmp不考虑字符串的长度,因此它是非二进制安全函数.
C的大多数标准库字符串函数可以归类为"非二进制安全",因为它依赖于空终止字符.
处理zend_string扩展代码时,应该使用Zend字符串函数(zend_string_*)而不是C的字符串库.
要修复以前的代码:
if (zend_string_equals(a, b)) {
php_printf("Equal!");
} else {
php_printf("Not equal");
}
Run Code Online (Sandbox Code Playgroud)
这现在正确打印"不相等".