baiyan所有视频:https://segmentfault.com/a/11...原视频地址:http://replay.xesv5.com/ll/24...本篇笔记部分图片取自视频中的片段,图片版权归视频原作者所有。malloc函数在PHP内存管理1笔记中有提到。malloc()函数会在分配的内存空间前面多分配32位,用来存放分配的大小和几个标志位,如图:那么是这样的吗?羊毛布?让我们写一个测试代码来验证:#includeintmain(){void*ptr=malloc(8);return1;}使用gdb调试这段代码:首先打印出ptr的地址,即0x602010,使用x命令回头查看20个内存单元(1个内存单元=4字节),所以一共显示了80个字节,后面的x以十六进制打印内容。我们发现紧邻0x602010地址的高32位全为0,没有任何内容,不符合我们的预期。上图只是最简单的思路,但大多数操作系统都是这样实现的:操作系统中有一个链表,记录空闲内存地址。当操作系统收到程序的申请时,会遍历链表,然后寻找第一个空间大于请求空间的堆节点,然后从空闲节点链表中删除该节点,并删除堆节点。分配给程序的空间点数。malloc函数的本质是它有一个所谓的空闲列表(FreeList),它将可用的内存块连接成一个长列表。当调用malloc函数时,它会沿着连接表寻找一个足够大的内存块来满足用户的请求(根据不同的算法(根据不同的算法(第一个找到的不小于请求大小的内存块分配给请求者,最合适的)申请大小的空闲内存分配给请求者,或者分配最大的空闲内存块)。然后,将内存块一分为二(一个块的大小等于用户请求的大小,另一个块的大小为剩余的字节)。接下来,将分配给用户的内存传递给用户,并将剩余的一块(如果有的话)返回给连接表。调用free函数时,会将用户释放的内存块连接到空闲链上。最后,空闲链会被切割成许多小的内存段。如果此时用户申请了一个大的内存段,那么空闲链上可能已经没有可以满足用户要求的段了。因此,malloc函数请求了一个延时,开始检查空闲链上的每个内存段,进行排序,将相邻的小空闲块合并成更大的内存块。如果无法获得满足要求的内存块,malloc函数将返回一个NULL指针。因此,在调用malloc动态申请内存块时,必须对返回值进行判断。结构与联合结构在PHP内存管理2笔记中,我们讲到一个特例:当b是char类型时,a和b的内存地址是相邻的;如果b是int类型,就会出现如图的情况。我们可以这样记:不管b后面的字段,a和b也是按照它们的最小公倍数对齐的(如果b是int类型,a和b的最小公倍数是4,按4对齐;如果b是char类型,最小公倍数是1,如果按1对齐,a和b会紧挨着出现。)如果不想对齐,有以下解决方案:不加优化参数编译时代码层面:在struct后面加关键字,比如redis中的sds简单动态字符串的实现:struct__attribute__((packed))sdshdr16{uint16_tlen;uint16_t分配;无符号字符标志;字符缓冲区[];只有一种类型的变量),也可以用来判断机器的字节顺序。宏定义宏是替换。关于下面代码的复杂宏替换问题,在PHP内存管理3笔记中已经有详细说明,这里不再赘述。#define_BIN_DATA_SIZE(num,size,elements,pages,x,y)size,staticconstuint32_tbin_data_size[]={ZEND_MM_BINS_INFO(_BIN_DATA_SIZE,x,y)};关于C语言宏定义中##等特殊符号的用法,参考:#define宏定义中的#、##、@#,这些符号的神奇用法PHP7中的基本变量在PHP7中,所有变量都用zval表示结构。一个zval是16字节;在PHP5中,一个zval是48字节。struct_zval_struct{zend_value值;联合u1;联合u2;};存储变量需要考虑两个要素:值和类型。变量值存储在PHP7中,变量值存储在zend_value联合体中。只有整数和浮点数类型直接存储在zend_value中,其他类型只存储一个指向专门存储该类型的结构体的指针。这个联合一共占用8个字节。typedefunion_zend_value{zend_longlval;//整数双dval;//浮点数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;//函数结构{uint32_tw1;uint32_tw2;}ww;//这个union一共有8B,这个结构体每个字段都是4B,因为所有的union字段共享一块内存,所以相当于取了union的一半}zend_value;变量类型存储在PHP7中,变量类型存储在zval中的u1union中:...union{struct{ZEND_ENDIAN_LOHI_4(zend_uchartype,/*此处使用unsignedchar存储PHP变量值的类型*/zend_uchartype_flags,zend_ucharconst_flags,zend_ucharreserved)/*EX(This)的调用信息*/}v;uint32_t类型信息;}u1;...PHP7中的所有变量类型:/*常规数据类型*/#defineIS_UNDEF0#defineIS_NULL1#defineIS_FALSE2#defineIS_TRUE3#defineIS_LONG4#defineIS_DOUBLE5#defineIS_STRING6#defineIS_ARRAY7#defineIS_OBJECT8#defineIS_RESOURCE9#defineIS_REFERENCE10/*常量表达式*/#defineIS_CONSTANT11#defineIS_CONSTANT_AST12/*假类型*/#define_IS_BOOL13#defineIS_CALLABLE14#defineIS_ITERABLE19#defineIS_VOID18/*内部类型*/#defineIS_INDIRECT15#defineIS_PTR17#define_IS_ERROR20String字符串基本结构设计在PHP7中字符串存储的数据结构的两个元素:字符串值和长度PHP7字符串存储结构设计:struct_zend_string{zend_refcounted_hgc;/*引用计数,与垃圾回收有关,暂不展开*/zend_ulongh;/*冗余hash值,在计算数组key的hash值时避免重复计算*/size_tlen;/*长度*/charval[1];/*灵活的数组,实际存放的是字符串值*/};二进制安全性的问题是从为什么存储长度衍生出来的。二进制安全:写入的数据和读取的数据完全一样,是二进制安全。详见PHPStringNotesStringcopywhenwriting看PHP代码如下: