Jinyun's Notes 🚀

没什么天赋,爱好也不多,但愿坚持做些喜欢的事情

0%

PHP 源码学习一

🤷‍♂️ 看到慕课网有大佬讲解 PHP 源码,既然来了,那就看看吧,以下为整理的笔记。

环境准备

1
2
3
4
5
6
7
8
9
10
11
12
// 之所以使用 hashicorp/bionic64,是因为这个镜像是官方的,坑少而已
$ vagrant init hashicorp/bionic64

// 这是我本地已经安装的一些镜像,有了镜像就可以在几分钟之内登录到一台全新的 Linux 系统中
$ vagrant box list
centos/7 (virtualbox, 2004.01)
hashicorp/bionic64 (virtualbox, 1.0.282)
laravel/homestead (virtualbox, 9.7.2)
ubuntu/xenial64 (virtualbox, 20210804.0.0)

// 需要漫长的等待,有可能还需要翻墙,或者你可以下载镜像后选择导入
$ vagrant up

编译安装

如果从 官网 下载,不需要进行 autoconf;如果从 Github 下载,需要在解压目录中执行 autoconf,经过本人安装折腾,认为从官网下载的包安装比较顺利。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
$ sudo -s
# apt-get update && apt-get upgrade
# apt-get install autoconf bison re2c pkg-config libxml2-dev libsqlite3-dev gdb -y
# cd ~ && mkdir codes
# cd ~/vagrant

// 安装 php80
# tar -zxvf php-src-php-8.0.1.tar.gz
# cd php-src-php-8.0.1
# autoconf
# ./configure --prefix=/home/vagrant/codes/php80 --enable-fpm --enable-debug
# make && make install
Installing shared extensions: /home/vagrant/codes/php80/lib/php/extensions/debug-non-zts-20200930/
Installing PHP CLI binary: /home/vagrant/codes/php80/bin/
Installing PHP CLI man page: /home/vagrant/codes/php80/php/man/man1/
Installing PHP FPM binary: /home/vagrant/codes/php80/sbin/
Installing PHP FPM defconfig: /home/vagrant/codes/php80/etc/
Installing PHP FPM man page: /home/vagrant/codes/php80/php/man/man8/
Installing PHP FPM status page: /home/vagrant/codes/php80/php/php/fpm/
Installing phpdbg binary: /home/vagrant/codes/php80/bin/
Installing phpdbg man page: /home/vagrant/codes/php80/php/man/man1/
Installing PHP CGI binary: /home/vagrant/codes/php80/bin/
Installing PHP CGI man page: /home/vagrant/codes/php80/php/man/man1/
Installing build environment: /home/vagrant/codes/php80/lib/php/build/
Installing header files: /home/vagrant/codes/php80/include/php/
Installing helper programs: /home/vagrant/codes/php80/bin/
program: phpize
program: php-config
Installing man pages: /home/vagrant/codes/php80/php/man/man1/
page: phpize.1
page: php-config.1
/vagrant/php-8.0.10/build/shtool install -c ext/phar/phar.phar /home/vagrant/codes/php80/bin/phar.phar
ln -s -f phar.phar /home/vagrant/codes/php80/bin/phar
Installing PDO headers: /home/vagrant/codes/php80/include/php/ext/pdo/

// 安装 php74
# tar -zxvf php-src-php-7.4.23.tar.gz
# cd php-src-php-7.4.23
# autoconf
# ./configure --prefix=/home/vagrant/codes/php74 --enable-fpm --enable-debug
# make && make install
Installing shared extensions: /home/vagrant/codes/php74/lib/php/extensions/debug-non-zts-20190902/
Installing PHP CLI binary: /home/vagrant/codes/php74/bin/
Installing PHP CLI man page: /home/vagrant/codes/php74/php/man/man1/
Installing PHP FPM binary: /home/vagrant/codes/php74/sbin/
Installing PHP FPM defconfig: /home/vagrant/codes/php74/etc/
Installing PHP FPM man page: /home/vagrant/codes/php74/php/man/man8/
Installing PHP FPM status page: /home/vagrant/codes/php74/php/php/fpm/
Installing phpdbg binary: /home/vagrant/codes/php74/bin/
Installing phpdbg man page: /home/vagrant/codes/php74/php/man/man1/
Installing PHP CGI binary: /home/vagrant/codes/php74/bin/
Installing PHP CGI man page: /home/vagrant/codes/php74/php/man/man1/
Installing build environment: /home/vagrant/codes/php74/lib/php/build/
Installing header files: /home/vagrant/codes/php74/include/php/
Installing helper programs: /home/vagrant/codes/php74/bin/
program: phpize
program: php-config
Installing man pages: /home/vagrant/codes/php74/php/man/man1/
page: phpize.1
page: php-config.1
/vagrant/php-7.4.23/build/shtool install -c ext/phar/phar.phar /home/vagrant/codes/php74/bin/phar.phar
ln -s -f phar.phar /home/vagrant/codes/php74/bin/phar
Installing PDO headers: /home/vagrant/codes/php74/include/php/ext/pdo/

// 安装 php73

# tar -zxvf php-src-php-7.3.30.tar.gz
# cd php-src-php-7.3.30
# autoconf
# ./configure --prefix=/home/vagrant/codes/php73 --enable-fpm --enable-debug
Installing shared extensions: /home/vagrant/codes/php73/lib/php/extensions/debug-non-zts-20180731/
Installing PHP CLI binary: /home/vagrant/codes/php73/bin/
Installing PHP CLI man page: /home/vagrant/codes/php73/php/man/man1/
Installing PHP FPM binary: /home/vagrant/codes/php73/sbin/
Installing PHP FPM defconfig: /home/vagrant/codes/php73/etc/
Installing PHP FPM man page: /home/vagrant/codes/php73/php/man/man8/
Installing PHP FPM status page: /home/vagrant/codes/php73/php/php/fpm/
Installing phpdbg binary: /home/vagrant/codes/php73/bin/
Installing phpdbg man page: /home/vagrant/codes/php73/php/man/man1/
Installing PHP CGI binary: /home/vagrant/codes/php73/bin/
Installing PHP CGI man page: /home/vagrant/codes/php73/php/man/man1/
Installing build environment: /home/vagrant/codes/php73/lib/php/build/
Installing header files: /home/vagrant/codes/php73/include/php/
Installing helper programs: /home/vagrant/codes/php73/bin/
program: phpize
program: php-config
Installing man pages: /home/vagrant/codes/php73/php/man/man1/
page: phpize.1
page: php-config.1
Installing PEAR environment: /home/vagrant/codes/php73/lib/php/
[PEAR] Archive_Tar - installed: 1.4.14
[PEAR] Console_Getopt - installed: 1.4.3
[PEAR] Structures_Graph- installed: 1.1.1
[PEAR] XML_Util - installed: 1.4.5
warning: pear/PEAR dependency package "pear/Archive_Tar" installed version 1.4.14 is not the recommended version 1.4.4
[PEAR] PEAR - installed: 1.10.13
Wrote PEAR system config file at: /home/vagrant/codes/php73/etc/pear.conf
You may want to add: /home/vagrant/codes/php73/lib/php to your php.ini include_path
/vagrant/php-7.3.30/build/shtool install -c ext/phar/phar.phar /home/vagrant/codes/php73/bin
ln -s -f phar.phar /home/vagrant/codes/php73/bin/phar
Installing PDO headers: /home/vagrant/codes/php73/include/php/ext/pdo/

基准测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
$ sudo -s

// php80 基准测试
# /home/vagrant/codes/php80/bin/php /vagrant/php-8.0.10/Zend/bench.php
simple 0.042
simplecall 0.018
simpleucall 0.076
simpleudcall 0.090
mandel 0.401
mandel2 0.356
ackermann(7) 0.100
ary(50000) 0.019
ary2(50000) 0.021
ary3(2000) 0.213
fibo(30) 0.312
hash1(50000) 0.051
hash2(500) 0.054
heapsort(20000) 0.109
matrix(20) 0.119
nestedloop(12) 0.085
sieve(30) 0.080
strcat(200000) 0.029
------------------------
Total 2.174
# /home/vagrant/codes/php80/bin/php /vagrant/php-8.0.10/Zend/micro_bench.php
empty_loop 0.076
func() 0.284 0.208
undef_func() 0.350 0.274
int_func() 0.113 0.037
$x = self::$x 0.344 0.268
self::$x = 0 0.270 0.194
isset(self::$x) 0.354 0.278
empty(self::$x) 0.363 0.287
$x = Foo::$x 0.279 0.203
Foo::$x = 0 0.198 0.122
isset(Foo::$x) 0.263 0.186
empty(Foo::$x) 0.282 0.206
self::f() 0.383 0.307
Foo::f() 0.345 0.269
$x = $this->x 0.488 0.412
$this->x = 0 0.223 0.147
$this->x += 2 0.511 0.435
++$this->x 0.340 0.264
--$this->x 0.350 0.274
$this->x++ 0.369 0.293
$this->x-- 0.333 0.256
isset($this->x) 0.732 0.656
empty($this->x) 0.347 0.270
$this->f() 0.325 0.249
$x = Foo::TEST 0.411 0.335
new Foo() 1.083 1.007
$x = TEST 0.208 0.132
$x = $_GET 0.390 0.314
$x = $GLOBALS['v'] 0.624 0.548
$x = $hash['v'] 0.475 0.399
$x = $str[0] 0.294 0.218
$x = $a ?: null 0.491 0.415
$x = $f ?: tmp 0.437 0.361
$x = $f ? $f : $a 0.351 0.275
$x = $f ? $f : tmp 0.312 0.236
------------------------
Total 12.997


// php74 基准测试
# /home/vagrant/codes/php74/bin/php /vagrant/php-7.4.23/Zend/bench.php
simple 0.068
simplecall 0.032
simpleucall 0.073
simpleudcall 0.087
mandel 0.429
mandel2 0.374
ackermann(7) 0.098
ary(50000) 0.019
ary2(50000) 0.021
ary3(2000) 0.211
fibo(30) 0.326
hash1(50000) 0.051
hash2(500) 0.057
heapsort(20000) 0.109
matrix(20) 0.134
nestedloop(12) 0.122
sieve(30) 0.070
strcat(200000) 0.021
------------------------
Total 2.303
# /home/vagrant/codes/php74/bin/php /vagrant/php-7.4.23/Zend/micro_bench.php
empty_loop 0.081
func() 0.346 0.265
undef_func() 0.478 0.397
int_func() 0.174 0.093
$x = self::$x 0.406 0.325
self::$x = 0 0.314 0.234
isset(self::$x) 0.411 0.330
empty(self::$x) 0.420 0.339
$x = Foo::$x 0.305 0.224
Foo::$x = 0 0.229 0.148
isset(Foo::$x) 0.304 0.223
empty(Foo::$x) 0.318 0.237
self::f() 0.461 0.381
Foo::f() 0.436 0.355
$x = $this->x 0.277 0.196
$this->x = 0 0.220 0.139
$this->x += 2 0.413 0.333
++$this->x 0.327 0.247
--$this->x 0.335 0.255
$this->x++ 0.351 0.270
$this->x-- 0.350 0.269
isset($this->x) 0.407 0.326
empty($this->x) 0.438 0.358
$this->f() 0.429 0.349
$x = Foo::TEST 0.428 0.347
new Foo() 1.193 1.113
$x = TEST 0.252 0.171
$x = $_GET 0.509 0.429
$x = $GLOBALS['v'] 0.876 0.795
$x = $hash['v'] 0.539 0.459
$x = $str[0] 0.361 0.280
$x = $a ?: null 0.435 0.354
$x = $f ?: tmp 0.392 0.312
$x = $f ? $f : $a 0.384 0.303
$x = $f ? $f : tmp 0.360 0.280
------------------------
Total 13.961


// php73 基准测试
# /home/vagrant/codes/php73/bin/php /vagrant/php-7.3.30/Zend/bench.php
simple 0.075
simplecall 0.025
simpleucall 0.118
simpleudcall 0.099
mandel 0.512
mandel2 0.540
ackermann(7) 0.135
ary(50000) 0.022
ary2(50000) 0.032
ary3(2000) 0.310
fibo(30) 0.460
hash1(50000) 0.068
hash2(500) 0.068
heapsort(20000) 0.160
matrix(20) 0.187
nestedloop(12) 0.147
sieve(30) 0.083
strcat(200000) 0.034
------------------------
Total 3.077
# /home/vagrant/codes/php73/bin/php /vagrant/php-7.3.30/Zend/micro_bench.php
empty_loop 0.084
func() 0.319 0.235
undef_func() 0.572 0.488
int_func() 0.151 0.067
$x = self::$x 0.319 0.235
self::$x = 0 0.306 0.222
isset(self::$x) 0.285 0.201
empty(self::$x) 0.300 0.216
$x = Foo::$x 0.243 0.159
Foo::$x = 0 0.246 0.162
isset(Foo::$x) 0.244 0.160
empty(Foo::$x) 0.254 0.170
self::f() 0.390 0.307
Foo::f() 0.353 0.269
$x = $this->x 0.262 0.178
$this->x = 0 0.206 0.122
$this->x += 2 0.365 0.281
++$this->x 0.265 0.181
--$this->x 0.267 0.183
$this->x++ 0.290 0.206
$this->x-- 0.296 0.212
isset($this->x) 0.379 0.295
empty($this->x) 0.375 0.291
$this->f() 0.399 0.315
$x = Foo::TEST 0.406 0.322
new Foo() 1.153 1.070
$x = TEST 0.232 0.148
$x = $_GET 0.447 0.363
$x = $GLOBALS['v'] 0.660 0.576
$x = $hash['v'] 0.471 0.387
$x = $str[0] 0.319 0.236
$x = $a ?: null 0.373 0.289
$x = $f ?: tmp 0.386 0.303
$x = $f ? $f : $a 0.346 0.262
$x = $f ? $f : tmp 0.325 0.241
------------------------
Total 12.285

新的特性

调试运行

常用的 GDB 命令

CommandDescription
rStart running program until a breakpoint or end of program
b funSet a breakpoint at the begining of function fun
b NSet a breakpoint at line number N of source file currently executing
b file.c:NSet a breakpoint at line number N of file file.c
d NRemove breakpoint number N
info breakList all breakpoints
cContinues/Resumes running the program until the next breakpoint or end of program
fRuns until the current function is finished
sRuns the next line of the program
s NRuns the next N lines of program
nLike s, but it does not step into functions
p varPrints the current value of the variable var
set var=valAssign val value to the variable var
btPrints a stack trace
qQuit from gdb

源码中的定义

  • 变量类型的定义:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/* Regular data types: Must be in sync with zend_variables.c. */
#define IS_UNDEF 0
#define IS_NULL 1
#define IS_FALSE 2
#define IS_TRUE 3
#define IS_LONG 4
#define IS_DOUBLE 5
#define IS_STRING 6
#define IS_ARRAY 7
#define IS_OBJECT 8
#define IS_RESOURCE 9
#define IS_REFERENCE 10
#define IS_CONSTANT_AST 11 /* Constant expressions */

/* Fake types used only for type hinting.
* These are allowed to overlap with the types below. */
#define IS_CALLABLE 12
#define IS_ITERABLE 13
#define IS_VOID 14
#define IS_STATIC 15
#define IS_MIXED 16

/* internal types */
#define IS_INDIRECT 12
#define IS_PTR 13
#define IS_ALIAS_PTR 14
#define _IS_ERROR 15

/* used for casts */
#define _IS_BOOL 17
#define _IS_NUMBER 18
  • _zend_value & _zend_sruct:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
typedef union _zend_value {
zend_long lval; /* long value */
double dval; /* double value */
zend_refcounted *counted;
zend_string *str;
zend_array *arr;
zend_object *obj;
zend_resource *res;
zend_reference *ref;
zend_ast_ref *ast;
zval *zv;
void *ptr;
zend_class_entry *ce;
zend_function *func;
struct {
uint32_t w1;
uint32_t w2;
} ww;
} zend_value;

struct _zval_struct {
zend_value value; /* value */
union {
uint32_t type_info;
struct {
ZEND_ENDIAN_LOHI_3(
zend_uchar type, /* active type */
zend_uchar type_flags,
union {
uint16_t extra; /* not further specified */
} u)
} v;
} u1;
union {
uint32_t next; /* hash collision chain */
uint32_t cache_slot; /* cache slot (for RECV_INIT) */
uint32_t opline_num; /* opline number (for FAST_CALL) */
uint32_t lineno; /* line number (for ast nodes) */
uint32_t num_args; /* arguments number for EX(This) */
uint32_t fe_pos; /* foreach position */
uint32_t fe_iter_idx; /* foreach iterator index */
uint32_t access_flags; /* class constant access flags */
uint32_t property_guard; /* single property guard */
uint32_t constant_flags; /* constant flags */
uint32_t extra; /* not further specified */
} u2;
};

测试程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
$a = 1;
echo $a;

$b = 3.14;
echo $b;

$c = null;
echo $c;

$d = true;
echo $d;

$e = false;
echo $e;

$f = 'string';
echo $f;

$g = [1, 2, 3];
echo $g;

$h = new \stdClass();
echo $h;
1
2
3
4
5
6
7
8
9
10
# gdb /home/vagrant/codes/php80/bin/php
(gdb) b ZEND_ECHO_SPEC_CV_HANDLER
Breakpoint 1 at 0x5c96a8: file /vagrant/php-8.0.10/Zend/zend_vm_execute.h, line 37184.
(gdb) r variables.php
Starting program: /home/vagrant/codes/php80/bin/php variables.php
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, ZEND_ECHO_SPEC_CV_HANDLER () at /vagrant/php-8.0.10/Zend/zend_vm_execute.h:37184
37184 SAVE_OPLINE();
  • 整型:
1
2
3
4
5
6
7
8
9
10
11
(gdb) n
37185 z = EX_VAR(opline->op1.var);
(gdb) n
37187 if (Z_TYPE_P(z) == IS_STRING) {
(gdb) p z
$1 = (zval *) 0x7ffff3814070
(gdb) p *z
$2 = {value = {lval = 1, dval = 4.9406564584124654e-324, counted = 0x1, str = 0x1, arr = 0x1, obj = 0x1, res = 0x1, ref = 0x1, ast = 0x1, zv = 0x1, ptr = 0x1,
ce = 0x1, func = 0x1, ww = {w1 = 1, w2 = 0}}, u1 = {type_info = 4, v = {type = 4 '\004', type_flags = 0 '\000', u = {extra = 0}}}, u2 = {next = 0,
cache_slot = 0, opline_num = 0, lineno = 0, num_args = 0, fe_pos = 0, fe_iter_idx = 0, access_flags = 0, property_guard = 0, constant_flags = 0, extra = 0}}
(gdb)
  • 浮点型:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(gdb) c
Continuing.
1
Breakpoint 1, ZEND_ECHO_SPEC_CV_HANDLER () at /vagrant/php-8.0.10/Zend/zend_vm_execute.h:37184
37184 SAVE_OPLINE();
(gdb) n
37185 z = EX_VAR(opline->op1.var);
(gdb) n
37187 if (Z_TYPE_P(z) == IS_STRING) {
(gdb) p z
$3 = (zval *) 0x7ffff3814080
(gdb) p *z
$4 = {value = {lval = 4614253070214989087, dval = 3.1400000000000001, counted = 0x40091eb851eb851f, str = 0x40091eb851eb851f, arr = 0x40091eb851eb851f,
obj = 0x40091eb851eb851f, res = 0x40091eb851eb851f, ref = 0x40091eb851eb851f, ast = 0x40091eb851eb851f, zv = 0x40091eb851eb851f, ptr = 0x40091eb851eb851f,
ce = 0x40091eb851eb851f, func = 0x40091eb851eb851f, ww = {w1 = 1374389535, w2 = 1074339512}}, u1 = {type_info = 5, v = {type = 5 '\005',
type_flags = 0 '\000', u = {extra = 0}}}, u2 = {next = 0, cache_slot = 0, opline_num = 0, lineno = 0, num_args = 0, fe_pos = 0, fe_iter_idx = 0,
access_flags = 0, property_guard = 0, constant_flags = 0, extra = 0}}
(gdb)
  • NULL 型:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(gdb) c
Continuing.
3.14
Breakpoint 1, ZEND_ECHO_SPEC_CV_HANDLER () at /vagrant/php-8.0.10/Zend/zend_vm_execute.h:37184
37184 SAVE_OPLINE();
(gdb) n
37185 z = EX_VAR(opline->op1.var);
(gdb) n
37187 if (Z_TYPE_P(z) == IS_STRING) {
(gdb) p z
$5 = (zval *) 0x7ffff3814090
(gdb) p *z
$6 = {value = {lval = 2, dval = 9.8813129168249309e-324, counted = 0x2, str = 0x2, arr = 0x2, obj = 0x2, res = 0x2, ref = 0x2, ast = 0x2, zv = 0x2, ptr = 0x2,
ce = 0x2, func = 0x2, ww = {w1 = 2, w2 = 0}}, u1 = {type_info = 1, v = {type = 1 '\001', type_flags = 0 '\000', u = {extra = 0}}}, u2 = {next = 0,
cache_slot = 0, opline_num = 0, lineno = 0, num_args = 0, fe_pos = 0, fe_iter_idx = 0, access_flags = 0, property_guard = 0, constant_flags = 0, extra = 0}}
(gdb)
  • 布尔 TRUE 型:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(gdb) c
Continuing.

Breakpoint 1, ZEND_ECHO_SPEC_CV_HANDLER () at /vagrant/php-8.0.10/Zend/zend_vm_execute.h:37184
37184 SAVE_OPLINE();
(gdb) n
37185 z = EX_VAR(opline->op1.var);
(gdb) n
37187 if (Z_TYPE_P(z) == IS_STRING) {
(gdb) p z
$7 = (zval *) 0x7ffff38140a0
(gdb) p *z
$8 = {value = {lval = 2, dval = 9.8813129168249309e-324, counted = 0x2, str = 0x2, arr = 0x2, obj = 0x2, res = 0x2, ref = 0x2, ast = 0x2, zv = 0x2, ptr = 0x2,
ce = 0x2, func = 0x2, ww = {w1 = 2, w2 = 0}}, u1 = {type_info = 3, v = {type = 3 '\003', type_flags = 0 '\000', u = {extra = 0}}}, u2 = {next = 0,
cache_slot = 0, opline_num = 0, lineno = 0, num_args = 0, fe_pos = 0, fe_iter_idx = 0, access_flags = 0, property_guard = 0, constant_flags = 0, extra = 0}}
(gdb)
  • 布尔 FALSE 型:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(gdb) c
Continuing.
1
Breakpoint 1, ZEND_ECHO_SPEC_CV_HANDLER () at /vagrant/php-8.0.10/Zend/zend_vm_execute.h:37184
37184 SAVE_OPLINE();
(gdb) n
37185 z = EX_VAR(opline->op1.var);
(gdb) n
37187 if (Z_TYPE_P(z) == IS_STRING) {
(gdb) p z
$9 = (zval *) 0x7ffff38140b0
(gdb) p *z
$10 = {value = {lval = 2, dval = 9.8813129168249309e-324, counted = 0x2, str = 0x2, arr = 0x2, obj = 0x2, res = 0x2, ref = 0x2, ast = 0x2, zv = 0x2, ptr = 0x2,
ce = 0x2, func = 0x2, ww = {w1 = 2, w2 = 0}}, u1 = {type_info = 2, v = {type = 2 '\002', type_flags = 0 '\000', u = {extra = 0}}}, u2 = {next = 0,
cache_slot = 0, opline_num = 0, lineno = 0, num_args = 0, fe_pos = 0, fe_iter_idx = 0, access_flags = 0, property_guard = 0, constant_flags = 0, extra = 0}}
(gdb)
  • 字符串型:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
(gdb) c
Continuing.

Breakpoint 1, ZEND_ECHO_SPEC_CV_HANDLER () at /vagrant/php-8.0.10/Zend/zend_vm_execute.h:37184
37184 SAVE_OPLINE();
(gdb) n
37185 z = EX_VAR(opline->op1.var);
(gdb) n
37187 if (Z_TYPE_P(z) == IS_STRING) {
(gdb) p z
$11 = (zval *) 0x7ffff38140c0
(gdb) p *z
$12 = {value = {lval = 93825011385696, dval = 4.6355714846336205e-310, counted = 0x555556798560, str = 0x555556798560, arr = 0x555556798560,
obj = 0x555556798560, res = 0x555556798560, ref = 0x555556798560, ast = 0x555556798560, zv = 0x555556798560, ptr = 0x555556798560, ce = 0x555556798560,
func = 0x555556798560, ww = {w1 = 1450804576, w2 = 21845}}, u1 = {type_info = 6, v = {type = 6 '\006', type_flags = 0 '\000', u = {extra = 0}}}, u2 = {
next = 0, cache_slot = 0, opline_num = 0, lineno = 0, num_args = 0, fe_pos = 0, fe_iter_idx = 0, access_flags = 0, property_guard = 0, constant_flags = 0,
extra = 0}}
(gdb) p $12.value.str
$13 = (zend_string *) 0x555556798560
(gdb) p *$12.value.str
$14 = {gc = {refcount = 1, u = {type_info = 470}}, h = 9223378990886268924, len = 6, val = "s"}
(gdb) p *$12.value.str.val@6
$15 = "string"
(gdb)
  • 数组型:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
(gdb) c
Continuing.
string
Breakpoint 1, ZEND_ECHO_SPEC_CV_HANDLER () at /vagrant/php-8.0.10/Zend/zend_vm_execute.h:37184
37184 SAVE_OPLINE();
(gdb) n
37185 z = EX_VAR(opline->op1.var);
(gdb) n
37187 if (Z_TYPE_P(z) == IS_STRING) {
(gdb) p z
$16 = (zval *) 0x7ffff38140d0
(gdb) p *z
$17 = {value = {lval = 140737279001440, dval = 6.9533454643786159e-310, counted = 0x7ffff3858360, str = 0x7ffff3858360, arr = 0x7ffff3858360,
obj = 0x7ffff3858360, res = 0x7ffff3858360, ref = 0x7ffff3858360, ast = 0x7ffff3858360, zv = 0x7ffff3858360, ptr = 0x7ffff3858360, ce = 0x7ffff3858360,
func = 0x7ffff3858360, ww = {w1 = 4085613408, w2 = 32767}}, u1 = {type_info = 775, v = {type = 7 '\a', type_flags = 3 '\003', u = {extra = 0}}}, u2 = {
next = 0, cache_slot = 0, opline_num = 0, lineno = 0, num_args = 0, fe_pos = 0, fe_iter_idx = 0, access_flags = 0, property_guard = 0, constant_flags = 0,
extra = 0}}
(gdb) p $17.value.arr
$18 = (zend_array *) 0x7ffff3858360
(gdb) p *$17.value.arr
$19 = {gc = {refcount = 2, u = {type_info = 7}}, u = {v = {flags = 20 '\024', _unused = 0 '\000', nIteratorsCount = 0 '\000', _unused2 = 0 '\000'},
flags = 20}, nTableMask = 4294967294, arData = 0x7ffff385c508, nNumUsed = 3, nNumOfElements = 3, nTableSize = 8, nInternalPointer = 0,
nNextFreeElement = 3, pDestructor = 0x555555a909a5 <zval_ptr_dtor>}
(gdb)
  • 对象型:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
(gdb) c
Continuing.

Warning: Array to string conversion in /home/vagrant/codes/tests/variables.php on line 21
Array
Breakpoint 1, ZEND_ECHO_SPEC_CV_HANDLER () at /vagrant/php-8.0.10/Zend/zend_vm_execute.h:37184
37184 SAVE_OPLINE();
(gdb) n
37185 z = EX_VAR(opline->op1.var);
(gdb) n
37187 if (Z_TYPE_P(z) == IS_STRING) {
(gdb) p z
$20 = (zval *) 0x7ffff38140e0
(gdb) p *z
$21 = {value = {lval = 140737278651440, dval = 6.9533454470863183e-310, counted = 0x7ffff3802c30, str = 0x7ffff3802c30, arr = 0x7ffff3802c30,
obj = 0x7ffff3802c30, res = 0x7ffff3802c30, ref = 0x7ffff3802c30, ast = 0x7ffff3802c30, zv = 0x7ffff3802c30, ptr = 0x7ffff3802c30, ce = 0x7ffff3802c30,
func = 0x7ffff3802c30, ww = {w1 = 4085263408, w2 = 32767}}, u1 = {type_info = 776, v = {type = 8 '\b', type_flags = 3 '\003', u = {extra = 0}}}, u2 = {
next = 0, cache_slot = 0, opline_num = 0, lineno = 0, num_args = 0, fe_pos = 0, fe_iter_idx = 0, access_flags = 0, property_guard = 0, constant_flags = 0,
extra = 0}}
(gdb) p $21.value.obj
$22 = (zend_object *) 0x7ffff3802c30
(gdb) p *$21.value.obj
$23 = {gc = {refcount = 1, u = {type_info = 8}}, handle = 1, ce = 0x5555567f41c0, handlers = 0x555556752620 <std_object_handlers>, properties = 0x0,
properties_table = {{value = {lval = 93825006738840, dval = 4.6355712550484294e-310, counted = 0x555556329d98, str = 0x555556329d98, arr = 0x555556329d98,
obj = 0x555556329d98, res = 0x555556329d98, ref = 0x555556329d98, ast = 0x555556329d98, zv = 0x555556329d98, ptr = 0x555556329d98, ce = 0x555556329d98,
func = 0x555556329d98, ww = {w1 = 1446157720, w2 = 21845}}, u1 = {type_info = 40, v = {type = 40 '(', type_flags = 0 '\000', u = {extra = 0}}}, u2 = {
next = 0, cache_slot = 0, opline_num = 0, lineno = 0, num_args = 0, fe_pos = 0, fe_iter_idx = 0, access_flags = 0, property_guard = 0,
constant_flags = 0, extra = 0}}}}
(gdb)
本笔记是笔者在学习和工作中的一些整理,如对您有用,请鼓励我继续写作