https://yq.aliyun.com/articles/38307

https://yq.aliyun.com/ziliao/132720

http://blog.liyiwei.cn/%E3%80%8A%E7%AE%97%E6%B3%95%E5%AF%BC%E8%AE%BA%E3%80%8B%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0%EF%BC%9A%E4%BA%8C%E5%8F%89%E6%9F%A5%E6%89%BE%E6%A0%91/

为避免系统调用malloc,free, php内核使用内存池来管理已经分配或释放的内存

小内存 数组+链表

大内存 树+链表

存放的是还未使用的内存,以及释放的内存(也可以看做未使用的内存)

有新的内存需要分配时,首先会在 小内存和大内存中查找,如果找不到 再mmap 256K大小的内存, 余下的内存 根据大小 是放到小内存里,还是放到大内存里

假设在大内存里找到了相应的内存,就要把这个结点删除,其实就是二叉有序树的删除,但php相关的源码还是看不懂

如果待删除的结点 同时有左子树和右子树,这时有两种方式
1)查找右子树中最小的结点a,特点就是该 结点 没有 左子树, 假设a的右子树为b,a的父结点为c,那么 c.左子树为b,同时b的父结点为c

2)查找左子树中最大的结点a,特点是该结点没有 右子树,只有左子树,假设 a的左子树为b, a的父结点为c,那么 c的左子树为b,同时b的父结点为c

假设现在的二叉树为

        160

        /

       92

       /\

      84 98

      /\    /\

    76  86  96 106

\

97

删除92 采用第一种方法,在92的右子树中查找最小左值,就是96,同时97做为98的左结点

        160

        /

       96

       /\

      84 98

      /\    /\

    76  86  97 106

static inline void zend_mm_remove_from_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
{
zend_mm_free_block *prev = mm_block->prev_free_block;
zend_mm_free_block *next = mm_block->next_free_block; ZEND_MM_CHECK_MAGIC(mm_block, MEM_BLOCK_FREED); if (EXPECTED(prev == mm_block)) {
zend_mm_free_block **rp, **cp; rp = &mm_block->child[mm_block->child[] != NULL];
prev = *rp;
if (EXPECTED(prev == NULL)) { } else {
while (*(cp = &(prev->child[prev->child[] != NULL])) != NULL) {
prev = *cp;
rp = cp;
}
*rp = NULL; subst_block:
ZEND_MM_CHECK_TREE(mm_block);
*mm_block->parent = prev;
prev->parent = mm_block->parent;
if ((prev->child[] = mm_block->child[])) {
ZEND_MM_CHECK_TREE(prev->child[]);
prev->child[]->parent = &prev->child[];
}
if ((prev->child[] = mm_block->child[])) {
ZEND_MM_CHECK_TREE(prev->child[]);
prev->child[]->parent = &prev->child[];
}
}
}
}

假设现在的二叉树为

        160

        /

       92

       /\

      84 98

      /\    /\

      76    96 106

现在要删除结点92,按上面的代码

rp = &mm_block->child[mm_block->child[1] != NULL]; rp为92的右子树,即98的地址

prev = *rp; prev为8

while (*(cp = &(prev->child[prev->child[] != NULL])) != NULL) {
prev = *cp;
rp = cp;
}

while( *(cp = &98[1]) != NULL){

  prev = 106;

}

prev->parent = mm_block->parent;
if ((prev->child[] = mm_block->child[])) {
ZEND_MM_CHECK_TREE(prev->child[]);
prev->child[]->parent = &prev->child[];
}
if ((prev->child[] = mm_block->child[])) {
ZEND_MM_CHECK_TREE(prev->child[]);
prev->child[]->parent = &prev->child[];
}

106的父结点 是92的父结点,即106的父结点是160

106的左了树为 92的左子树 即 106的左子结点为84

106的右子树为 92的右子结,即106的右子结点 为98, 是不是不太对劲,这不符合二叉排序树的规则,因为右子树要大于他的父结点的

        160

        /

       106

       /\

      84 98

      /\    /\

      76    96

php 内存分配新的更多相关文章

  1. JVM内存分配策略

    在 JVM内存垃圾回收方法 中,我们已经详细讨论了内存回收,但是,我们程序中生成的对象是如何进行分配的呢?以下所述针对的是HotSpot虚拟机. 1.Java堆结构 以HotSpot为例,如下图: H ...

  2. 小白请教几个关于Java虚拟机内存分配策略的问题

    最近在看周志明所著的<深入理解Java虚拟机>,有几个问题不太明白,希望对虚拟机有研究的哥们儿帮我解答一下.先说一下我进行试验的环境: 操作系统:Mac OS X 10.11.6 EI C ...

  3. Linux内核笔记--内存管理之用户态进程内存分配

    内核版本:linux-2.6.11 Linux在加载一个可执行程序的时候做了种种复杂的工作,内存分配是其中非常重要的一环,作为一个linux程序员必然会想要知道这个过程到底是怎么样的,内核源码会告诉你 ...

  4. java中内存分配策略及堆和栈的比较

    Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间 ...

  5. C语言内存分配

      (1)代码区(text segment).存放CPU执行的机器指令(machine instructions).通常,代码区是可共享的 (即另外的执行程序可以调用它),因为对于频繁被执行的程序,只 ...

  6. C标准库-数值字符串转换与内存分配函数

    原文链接:http://www.orlion.ga/977/ 一.数值字符串转换函数 #include <stdlib.h> int atoi(const char *nptr); dou ...

  7. C++指针和动态内存分配

    指针和动态内存分配 数组与指针 数组 数组名是一个指针常量. 数组名传递数据时,传递的是地址. 数组作为函数参数时不指定第一维大小. 对象数组 A a[2] = {A(1,2)}; 执行时先调用有参数 ...

  8. SQLite剖析之动态内存分配

    SQLite通过动态内存分配来获取各种对象(例如数据库连接和SQL预处理语句)所需内存.建立数据库文件的内存Cache.保存查询结果. 1.特性    SQLite内核和它的内存分配子系统提供以下特性 ...

  9. C和指针 第十一章 动态内存分配

    声明数组时,必须指定数组长度,才可以编译,但是如果需要在运行时,指定数组的长度的话,那么就需要动态的分配内存. C函数库stdlib.h提供了两个函数,malloc和free,分别用于执行动态内存分配 ...

随机推荐

  1. CVE-2017-7494:Linux Samba named pipe漏洞

    描述: 漏洞是由于代码中一个管道申请命令的判断导致的,可以通过构造特定请求执行上传的so文件. 漏洞影响了Samba 3.5.0 之后到4.6.4/4.5.10/4.4.14中间的所有版本. 测试: ...

  2. BaseSEOPage统一设置网站SEO

    代码: public class BaseSeoPage : System.Web.UI.Page { protected override void OnPreLoad(EventArgs e) { ...

  3. DALSA网口线扫相机SDK开发详解例程(C#版)

    首先吐槽一句,官方的demos写的真的不好,坑爹啊.对于小白来说,开发官方demos为我所用太难了.为什么呢?因为它Dalsa的DALSA.SaperaLT.SapClassBasic.dll中,不仅 ...

  4. Laravel 配置文件操作方法

    1)laravel 的所以配置文件都在根目录下的 config 目录里,直接看一个配置文件的名字就知道是做什么的了,这里不说了 2)读取配置的方法 $value = config('app.timez ...

  5. ESXi系统命令行下启动虚拟机

    从命令行启动虚拟机: 用命令列出虚拟机的ID:vim-cmd vmsvc/getallvms |grep <vm name>注意: 第一列输出是vmid. 用命令查看虚拟机启动状态:vim ...

  6. 没有Home键之后的iPhone会是什么样子?

    以下内容由Mockplus团队翻译整理,仅供学习交流,Mockplus是更快更简单的原型设计工具. 之前笔者推测新一代的iPhone不会再有“Home”键.果不其然,9月13日苹果发布会证实了笔者的观 ...

  7. MyEclipse中Web项目文件名上红色和黄色感叹号处理

      MyEclipse中Web项目文件名上红色和黄色感叹号处理     先说红色感叹号: 那就是代表错误,说明你引用的JAR包位置无效,所以,你应该重新将包导入到工程里面去,这个具体应该会吧,如果是初 ...

  8. python使用git进行版本控制1

    首先,选择一个合适的地方,创建一个空目录: $ mkdir learngit $ cd learngit $ pwd /Users/michael/learngit pwd命令用于显示当前目录. 如果 ...

  9. [javascript]两段 javaScript 代码的逻辑比较

    两段 javaScript 代码的逻辑比较: #1 if(tagName.length < 3){    $(this).parent().addClass('active');    tagN ...

  10. Android-MediaPlayer-视频频播放-异步准备

    上两篇博客,Android-MediaPlayer-音频播放-普通准备,Android-MediaPlayer-音频播放-异步准备,主要是讲解了音频(.mp3文件)音乐