• 图文结合纯c手写内存池


    前言

      本文从零到一,手把手实现一个内存池。

      比较出名的内存池有jemalloc和tcmalloc,这两个都是全局内存池,比较推荐使用tcmalloc。

      本专栏知识点是通过零声教育的线上课学习,进行梳理总结写下文章,对c/c++linux课程感兴趣的读者,可以点击链接 C/C++后台高级服务器课程介绍 详细查看课程的服务。

    为什么要用内存池

      为什么要用内存池?首先,在7 * 24h的服务器中如果不使用内存池,而使用malloc和free,那么就非常容易产生内存碎片,早晚都会申请内存失败;并且在比较复杂的代码或者继承的屎山中,非常容易出现内存泄漏导致mmo的问题。

      为了解决这两个问题,内存池就应运而生了。内存池预先分配一大块内存来做一个内存池,业务中的内存分配和释放都由这个内存池来管理,内存池内的内存不足时其内部会自己申请。所以内存碎片的问题就交由内存池的算法来优化,而内存泄漏的问题只需要遵守内存池提供的api,就非常容易避免内存泄漏了。

      即使出现了内存泄漏,排查的思路也很清晰。1.检查是不是内存池的问题;2.如果不是内存池的问题,就检查是不是第三方库的内存泄漏。

    内存池的使用场景

    1. 全局内存池
    2. 一个连接一个内存池(本文实现这个场景的内存池)

    设计一个内存池

    总体介绍

      由于本文是一个连接一个内存池,所以后续介绍和代码都是以4k为分界线,大于4k的我们认为是大块内存;小于4k的我们认为是小块内存。并且注意这里的4k,并不是严格遵照4096,而是在描述上,用4k比较好描述。

      在真正使用内存之前,内存池提前分配一定数量且大小相等的内存块以作备用,当真正被用户调用api分配内存的时候,直接从内存块中获取内存(指小块内存),当内存块不够用了,再有内存池取申请新的内存块。而如果是需要大块内存,则内存池直接申请大块内存再返回给用户。

      内存池:就是将这些提前申请的内存块组织管理起来的数据结构,内存池实现原理主要分为分配,回收,扩容三部分。

      内存池原理之小块内存分配=> 内存池预申请一块4k的内存块,这里称为block,即block=4k内存块。当用户向内存池申请内存size小于4k时,内存池从block的空间中划分出去size空间,当再有新申请时,再划分出去。扩容=> 直到block中的剩余空间不足以分配size大小,那么此时内存池会再次申请一块block,再从新的block中划分size空间给用户。回收=> 每一次申请小内存,都会在对应的block中引用计数加1,每一次释放小内存时,都会在block中引用计数减1,只有当引用计数为零的时候,才会回收block使他重新成为空闲空间,以便重复利用空间。这样,内存池避免频繁向内核申请/释放内存,从而提高系统性能。

      内存池原理之大块内存分配=> 因为大块内存是大于4k的,所以内存池不预先申请内存,也就是用户申请的时候,内存池再申请内存,然后返回给用户。扩容=> 大块内存不存在扩容。回收=> 对于大块内存来说,回收就直接free掉即可。

      上面理论讲完了,下面来介绍如何管理小块内存和大块内存。

    小块内存的分配与管理

      在创建内存池的时候,会预先申请一块4k的内存,并且在起始处将pool的结构体和node的结构体放进去,从last开始一直到end都是空闲内存,中间的区域就用来存储小块内存。每一次mp_malloc,就将last指针后移,直到 e n d − l a s t < s i z e end - last < size endlast<size 时,进行扩容,将新block的last后移即可。

    • 初始状态在这里插入图片描述
    • 分配内存在这里插入图片描述
    • 扩容
      在这里插入图片描述

    大块内存的分配与管理

      对于大块内存,前面已经说了,用户申请的时候,内存池才申请

    • 申请一块大内存
      在这里插入图片描述

    • 再申请一块大内存
      在这里插入图片描述

    内存池代码实现

    向外提供的api

    • mp_create_pool:创建一个线程池,其核心是创建struct mp_pool_s这个结构体,并申请4k内存,将各个指针指向上文初始状态的图一样。
    • mp_destroy_pool:销毁内存池,遍历小块结构体和大块结构体,进行free释放内存
    • mp_malloc:提供给用户申请内存的api
    • mp_calloc:通过mp_malloc申请内存后置零,相当于calloc
    • mp_free:释放由mp_malloc返回的内存
    • mp_reset_pool:将block的last置为初始状态,销毁所有大块内存
    • monitor_mp_poll:监控内存池状态
    struct mp_pool_s *mp_create_pool(size_t size);
    
    void mp_destroy_pool(struct mp_pool_s *pool);
    
    void *mp_malloc(struct mp_pool_s *pool, size_t size);
    
    void *mp_calloc(struct mp_pool_s *pool, size_t size);
    
    void mp_free(struct mp_pool_s *pool, void *p);
    
    void mp_reset_pool(struct mp_pool_s *pool);
    
    void monitor_mp_poll(struct mp_pool_s *pool, char *tk);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    相关结构体的定义

      mp_pool_s 就是整个内存池的管理结构,我们做的内存池是一个连接一个内存池,所以对于整个程序而言,内存池对象是有很多个的。
      可能读者会有疑问,有了head,为什么还有current,是因为如果一个block剩余空间小于size超过一定次数后,将current指向下一个block,这样就加快内存分配效率,减少遍历次数。

    //每4k一block结点
    struct mp_node_s {
        unsigned char *end;//块的结尾
        unsigned char *last;//使用到哪了
        struct mp_node_s *next;//链表
        int quote;//引用计数
        int failed;//失效次数
    };
    
    struct mp_large_s {
        struct mp_large_s *next;//链表
        int size;//alloc的大小
        void *alloc;//大块内存的起始地址
    };
    
    struct mp_pool_s {
        struct mp_large_s *large;
        struct mp_node_s *head;
        struct mp_node_s *current;
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    内存对齐

    访问速度是内存对齐的原因之一,另外一个原因是某些平台(arm)不支持未内存对齐的访问

      在4k里面划分内存,那么必然有很多地方是不对齐的,所以这里提供两个内存对齐的函数。那么为什么要内存对齐呢?其一:提高访问速度;其二:某些平台arm不支持未对其的内存访问,会出错。

    #define mp_align(n, alignment) (((n)+(alignment-1)) & ~(alignment-1))
    #define mp_align_ptr(p, alignment) (void *)((((size_t)p)+(alignment-1)) & ~(alignment-1))
    
    • 1
    • 2

    创建与销毁内存池

      创建一个线程池,其核心是创建struct mp_pool_s这个结构体,并申请4k内存,将各个指针指向上文初始状态的图一样。
      销毁内存池,遍历小块结构体和大块结构体,进行free释放内存。

    //创建内存池
    struct mp_pool_s *mp_create_pool(size_t size) {
        struct mp_pool_s *pool;
        if (size < PAGE_SIZE || size % PAGE_SIZE != 0) {
            size = PAGE_SIZE;
        }
        //分配4k以上不用malloc,用posix_memalign
        /*
            int posix_memalign (void **memptr, size_t alignment, size_t size);
         */
    
        int ret = posix_memalign((void **) &pool, MP_ALIGNMENT, size); //4K + mp_pool_s
        if (ret) {
            return NULL;
        }
        pool->large = NULL;
        pool->current = pool->head = (unsigned char *) pool + sizeof(struct mp_pool_s);
        pool->head->last = (unsigned char *) pool + sizeof(struct mp_pool_s) + sizeof(struct mp_node_s);
        pool->head->end = (unsigned char *) pool + PAGE_SIZE;
        pool->head->failed = 0;
    
        return pool;
    }
    
    //销毁内存池
    void mp_destroy_pool(struct mp_pool_s *pool) {
        struct mp_large_s *large;
        for (large = pool->large; large; large = large->next) {
            if (large->alloc) {
                free(large->alloc);
            }
        }
    
        struct mp_node_s *cur, *next;
        cur = pool->head->next;
    
        while (cur) {
            next = cur->next;
            free(cur);
            cur = next;
        }
        free(pool);
    }
    
    • 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

    在这里插入图片描述

    提供给用户的内存申请api

      申请的内存以size做区分,如果大于4k就分配大块内存,小于4k就去block里面划分。

    //分配内存
    void *mp_malloc(struct mp_pool_s *pool, size_t size) {
        if (size <= 0) {
            return NULL;
        }
        if (size > PAGE_SIZE - sizeof(struct mp_node_s)) {
            //large
            return mp_malloc_large(pool, size);
        }
        else {
            //small
            unsigned char *mem_addr = NULL;
            struct mp_node_s *cur = NULL;
            cur = pool->current;
            while (cur) {
                mem_addr = mp_align_ptr(cur->last, MP_ALIGNMENT);
                if (cur->end - mem_addr >= size) {
                    cur->quote++;//引用+1
                    cur->last = mem_addr + size;
                    return mem_addr;
                }
                else {
                    cur = cur->next;
                }
            }
            return mp_malloc_block(pool, size);// open new space
        }
    }
    void *mp_calloc(struct mp_pool_s *pool, size_t size) {
        void *mem_addr = mp_malloc(pool, size);
        if (mem_addr) {
            memset(mem_addr, 0, size);
        }
        return mem_addr;
    }
    
    • 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

    小块内存block扩容

       所有的block都 e n d − l a s t < s i z e end - last < size endlast<size 时,进行扩容,将新block的last后移即可。

    //new block 4k
    void *mp_malloc_block(struct mp_pool_s *pool, size_t size) {
        unsigned char *block;
        int ret = posix_memalign((void **) &block, MP_ALIGNMENT, PAGE_SIZE); //4K
        if (ret) {
            return NULL;
        }
        struct mp_node_s *new_node = (struct mp_node_s *) block;
        new_node->end = block + PAGE_SIZE;
        new_node->next = NULL;
    
        unsigned char *ret_addr = mp_align_ptr(block + sizeof(struct mp_node_s), MP_ALIGNMENT);
    
        new_node->last = ret_addr + size;
        new_node->quote++;
    
        struct mp_node_s *current = pool->current;
        struct mp_node_s *cur = NULL;
    
        for (cur = current; cur->next; cur = cur->next) {
            if (cur->failed++ > 4) {
                current = cur->next;
            }
        }
        //now cur = last node
        cur->next = new_node;
        pool->current = current;
        return ret_addr;
    }
    
    • 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

    分配大块内存

    //size>4k
    void *mp_malloc_large(struct mp_pool_s *pool, size_t size) {
        unsigned char *big_addr;
        int ret = posix_memalign((void **) &big_addr, MP_ALIGNMENT, size); //size
        if (ret) {
            return NULL;
        }
    
        struct mp_large_s *large;
        //released struct large resume
        int n = 0;
        for (large = pool->large; large; large = large->next) {
            if (large->alloc == NULL) {
                large->size = size;
                large->alloc = big_addr;
                return big_addr;
            }
            if (n++ > 3) {
                break;// 为了避免过多的遍历,限制次数
            }
        }
        large = mp_malloc(pool, sizeof(struct mp_large_s));
        if (large == NULL) {
            free(big_addr);
            return NULL;
        }
        large->size = size;
        large->alloc = big_addr;
        large->next = pool->large;
        pool->large = large;
        return big_addr;
    }
    
    • 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

    释放内存

      如果是大块内存,找到之后直接释放;如果是小块内存,将引用计数减1,如果引用计数为0则重置last。

    //释放内存
    void mp_free(struct mp_pool_s *pool, void *p) {
        struct mp_large_s *large;
        for (large = pool->large; large; large = large->next) {//大块
            if (p == large->alloc) {
                free(large->alloc);
                large->size = 0;
                large->alloc = NULL;
                return;
            }
        }
        //小块 引用-1
        struct mp_node_s *cur = NULL;
        for (cur = pool->head; cur; cur = cur->next) {
    //        printf("cur:%p   p:%p   end:%p\n", (unsigned char *) cur, (unsigned char *) p, (unsigned char *) cur->end);
            if ((unsigned char *) cur <= (unsigned char *) p && (unsigned char *) p <= (unsigned char *) cur->end) {
                cur->quote--;
                if (cur->quote == 0) {
                    if (cur == pool->head) {
                        pool->head->last = (unsigned char *) pool + sizeof(struct mp_pool_s) + sizeof(struct mp_node_s);
                    }
                    else {
                        cur->last = (unsigned char *) cur + sizeof(struct mp_node_s);
                    }
                    cur->failed = 0;
                    pool->current = pool->head;
                }
                return;
            }
        }
    }
    
    • 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

    内存池测试

    //
    // Created by 68725 on 2022/7/26.
    //
    #include 
    #include 
    #include 
    
    #define PAGE_SIZE 4096
    #define MP_ALIGNMENT 16
    #define mp_align(n, alignment) (((n)+(alignment-1)) & ~(alignment-1))
    #define mp_align_ptr(p, alignment) (void *)((((size_t)p)+(alignment-1)) & ~(alignment-1))
    
    //每4k一block结点
    struct mp_node_s {
        unsigned char *end;//块的结尾
        unsigned char *last;//使用到哪了
        struct mp_node_s *next;//链表
        int quote;//引用计数
        int failed;//失效次数
    };
    
    struct mp_large_s {
        struct mp_large_s *next;//链表
        int size;//alloc的大小
        void *alloc;//大块内存的起始地址
    };
    
    struct mp_pool_s {
        struct mp_large_s *large;
        struct mp_node_s *head;
        struct mp_node_s *current;
    };
    
    struct mp_pool_s *mp_create_pool(size_t size);
    
    void mp_destroy_pool(struct mp_pool_s *pool);
    
    void *mp_malloc(struct mp_pool_s *pool, size_t size);
    
    void *mp_calloc(struct mp_pool_s *pool, size_t size);
    
    void mp_free(struct mp_pool_s *pool, void *p);
    
    void mp_reset_pool(struct mp_pool_s *pool);
    
    void monitor_mp_poll(struct mp_pool_s *pool, char *tk);
    
    
    void mp_reset_pool(struct mp_pool_s *pool) {
        struct mp_node_s *cur;
        struct mp_large_s *large;
    
        for (large = pool->large; large; large = large->next) {
            if (large->alloc) {
                free(large->alloc);
            }
        }
    
        pool->large = NULL;
        pool->current = pool->head;
        for (cur = pool->head; cur; cur = cur->next) {
            cur->last = (unsigned char *) cur + sizeof(struct mp_node_s);
            cur->failed = 0;
            cur->quote = 0;
        }
    }
    
    //创建内存池
    struct mp_pool_s *mp_create_pool(size_t size) {
        struct mp_pool_s *pool;
        if (size < PAGE_SIZE || size % PAGE_SIZE != 0) {
            size = PAGE_SIZE;
        }
        //分配4k以上不用malloc,用posix_memalign
        /*
            int posix_memalign (void **memptr, size_t alignment, size_t size);
         */
    
        int ret = posix_memalign((void **) &pool, MP_ALIGNMENT, size); //4K + mp_pool_s
        if (ret) {
            return NULL;
        }
        pool->large = NULL;
        pool->current = pool->head = (unsigned char *) pool + sizeof(struct mp_pool_s);
        pool->head->last = (unsigned char *) pool + sizeof(struct mp_pool_s) + sizeof(struct mp_node_s);
        pool->head->end = (unsigned char *) pool + PAGE_SIZE;
        pool->head->failed = 0;
    
        return pool;
    }
    
    //销毁内存池
    void mp_destroy_pool(struct mp_pool_s *pool) {
        struct mp_large_s *large;
        for (large = pool->large; large; large = large->next) {
            if (large->alloc) {
                free(large->alloc);
            }
        }
    
        struct mp_node_s *cur, *next;
        cur = pool->head->next;
    
        while (cur) {
            next = cur->next;
            free(cur);
            cur = next;
        }
        free(pool);
    }
    
    //size>4k
    void *mp_malloc_large(struct mp_pool_s *pool, size_t size) {
        unsigned char *big_addr;
        int ret = posix_memalign((void **) &big_addr, MP_ALIGNMENT, size); //size
        if (ret) {
            return NULL;
        }
    
        struct mp_large_s *large;
        //released struct large resume
        int n = 0;
        for (large = pool->large; large; large = large->next) {
            if (large->alloc == NULL) {
                large->size = size;
                large->alloc = big_addr;
                return big_addr;
            }
            if (n++ > 3) {
                break;// 为了避免过多的遍历,限制次数
            }
        }
        large = mp_malloc(pool, sizeof(struct mp_large_s));
        if (large == NULL) {
            free(big_addr);
            return NULL;
        }
        large->size = size;
        large->alloc = big_addr;
        large->next = pool->large;
        pool->large = large;
        return big_addr;
    }
    
    //new block 4k
    void *mp_malloc_block(struct mp_pool_s *pool, size_t size) {
        unsigned char *block;
        int ret = posix_memalign((void **) &block, MP_ALIGNMENT, PAGE_SIZE); //4K
        if (ret) {
            return NULL;
        }
        struct mp_node_s *new_node = (struct mp_node_s *) block;
        new_node->end = block + PAGE_SIZE;
        new_node->next = NULL;
    
        unsigned char *ret_addr = mp_align_ptr(block + sizeof(struct mp_node_s), MP_ALIGNMENT);
    
        new_node->last = ret_addr + size;
        new_node->quote++;
    
        struct mp_node_s *current = pool->current;
        struct mp_node_s *cur = NULL;
    
        for (cur = current; cur->next; cur = cur->next) {
            if (cur->failed++ > 4) {
                current = cur->next;
            }
        }
        //now cur = last node
        cur->next = new_node;
        pool->current = current;
        return ret_addr;
    }
    
    //分配内存
    void *mp_malloc(struct mp_pool_s *pool, size_t size) {
        if (size <= 0) {
            return NULL;
        }
        if (size > PAGE_SIZE - sizeof(struct mp_node_s)) {
            //large
            return mp_malloc_large(pool, size);
        }
        else {
            //small
            unsigned char *mem_addr = NULL;
            struct mp_node_s *cur = NULL;
            cur = pool->current;
            while (cur) {
                mem_addr = mp_align_ptr(cur->last, MP_ALIGNMENT);
                if (cur->end - mem_addr >= size) {
                    cur->quote++;//引用+1
                    cur->last = mem_addr + size;
                    return mem_addr;
                }
                else {
                    cur = cur->next;
                }
            }
            return mp_malloc_block(pool, size);// open new space
        }
    }
    
    void *mp_calloc(struct mp_pool_s *pool, size_t size) {
        void *mem_addr = mp_malloc(pool, size);
        if (mem_addr) {
            memset(mem_addr, 0, size);
        }
        return mem_addr;
    }
    
    //释放内存
    void mp_free(struct mp_pool_s *pool, void *p) {
        struct mp_large_s *large;
        for (large = pool->large; large; large = large->next) {//大块
            if (p == large->alloc) {
                free(large->alloc);
                large->size = 0;
                large->alloc = NULL;
                return;
            }
        }
        //小块 引用-1
        struct mp_node_s *cur = NULL;
        for (cur = pool->head; cur; cur = cur->next) {
    //        printf("cur:%p   p:%p   end:%p\n", (unsigned char *) cur, (unsigned char *) p, (unsigned char *) cur->end);
            if ((unsigned char *) cur <= (unsigned char *) p && (unsigned char *) p <= (unsigned char *) cur->end) {
                cur->quote--;
                if (cur->quote == 0) {
                    if (cur == pool->head) {
                        pool->head->last = (unsigned char *) pool + sizeof(struct mp_pool_s) + sizeof(struct mp_node_s);
                    }
                    else {
                        cur->last = (unsigned char *) cur + sizeof(struct mp_node_s);
                    }
                    cur->failed = 0;
                    pool->current = pool->head;
                }
                return;
            }
        }
    }
    
    void monitor_mp_poll(struct mp_pool_s *pool, char *tk) {
        printf("\r\n\r\n------start monitor poll------%s\r\n\r\n", tk);
        struct mp_node_s *head = NULL;
        int i = 0;
        for (head = pool->head; head; head = head->next) {
            i++;
            if (pool->current == head) {
                printf("current==>第%d块\n", i);
            }
            if (i == 1) {
                printf("第%02d块small block  已使用:%4ld  剩余空间:%4ld  引用:%4d  failed:%4d\n", i,
                       (unsigned char *) head->last - (unsigned char *) pool,
                       head->end - head->last, head->quote, head->failed);
            }
            else {
                printf("第%02d块small block  已使用:%4ld  剩余空间:%4ld  引用:%4d  failed:%4d\n", i,
                       (unsigned char *) head->last - (unsigned char *) head,
                       head->end - head->last, head->quote, head->failed);
            }
        }
        struct mp_large_s *large;
        i = 0;
        for (large = pool->large; large; large = large->next) {
            i++;
            if (large->alloc != NULL) {
                printf("第%d块large block  size=%d\n", i, large->size);
            }
        }
        printf("\r\n\r\n------stop monitor poll------\r\n\r\n");
    }
    
    
    
    int main() {
        struct mp_pool_s *p = mp_create_pool(PAGE_SIZE);
        monitor_mp_poll(p, "create memory pool");
    #if 0
        printf("mp_align(5, %d): %d, mp_align(17, %d): %d\n", MP_ALIGNMENT, mp_align(5, MP_ALIGNMENT), MP_ALIGNMENT,
               mp_align(17, MP_ALIGNMENT));
        printf("mp_align_ptr(p->current, %d): %p, p->current: %p\n", MP_ALIGNMENT, mp_align_ptr(p->current, MP_ALIGNMENT),
               p->current);
    #endif
        void *mp[30];
        int i;
        for (i = 0; i < 30; i++) {
            mp[i] = mp_malloc(p, 512);
        }
        monitor_mp_poll(p, "申请512字节30个");
    
        for (i = 0; i < 30; i++) {
            mp_free(p, mp[i]);
        }
        monitor_mp_poll(p, "销毁512字节30个");
    
        int j;
        for (i = 0; i < 50; i++) {
            char *pp = mp_calloc(p, 32);
            for (j = 0; j < 32; j++) {
                if (pp[j]) {
                    printf("calloc wrong\n");
                    exit(-1);
                }
            }
        }
        monitor_mp_poll(p, "申请32字节50个");
    
        for (i = 0; i < 50; i++) {
            char *pp = mp_malloc(p, 3);
        }
        monitor_mp_poll(p, "申请3字节50个");
    
    
        void *pp[10];
        for (i = 0; i < 10; i++) {
            pp[i] = mp_malloc(p, 5120);
        }
        monitor_mp_poll(p, "申请大内存5120字节10个");
    
        for (i = 0; i < 10; i++) {
            mp_free(p, pp[i]);
        }
        monitor_mp_poll(p, "销毁大内存5120字节10个");
    
        mp_reset_pool(p);
        monitor_mp_poll(p, "reset pool");
    
        for (i = 0; i < 100; i++) {
            void *s = mp_malloc(p, 256);
        }
        monitor_mp_poll(p, "申请256字节100个");
    
        mp_destroy_pool(p);
        return 0;
    }
    
    • 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
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337

    在这里插入图片描述

    nginx内存池对比分析

    相关结构体定义对比

    在这里插入图片描述

    创建内存池对比

    在这里插入图片描述

    内存申请对比

    在这里插入图片描述

  • 相关阅读:
    【信息学CSP-J近16年历年真题64题】真题练习与解析 第7题之表达式
    60天零基础干翻C++————双指针问题
    基于图关系归纳偏差的小样本交通预测
    Vue中el-table条件渲染防止样式乱掉
    一个开源的汽修rbac后台管理系统项目,基于若依框架,实现了activiti工作流,附源码
    字符串ASCLL排序 Java
    发现Spring事务的一个实锤bug,官方还拒不承认?你来评评理...
    isEmpty() 和 null的区别
    memcpy和memmove的模拟实现,思路详解+代码实现
    请立即修复!服务器巨头核心固件曝7个高危漏洞
  • 原文地址:https://blog.csdn.net/qq_42956653/article/details/126005923