Zi 字媒體
2017-07-25T20:27:27+00:00
C/C++ 記憶池[嵌入式系統有限度的使用動態配置記憶體]
資料來源: https://blog.csdn.net/xinghun_4/article/details/5967840
http://tjpm.blog.chinaunix.net/uid-23969156-id-1743561.html
https://blog.csdn.net/weixin_40203143/article/details/85217972
GITHUB: https://github.com/jash-git/C_Memory-_Pool_Project
01.
/*
* fpool.h (fixed memory pool)
* author: xinghun_4
*/
#ifndef _FPOOL_H
#define _FPOOL_H
int mem_pool_init(int base_size, int links);
void mem_pool_destroy(void);
void print_mem_pool_info(void);
void *mem_malloc(int size);
void mem_free(void *ptr);
#endif
/*
* fpool.c (fixed memory pool)
* author: xinghun_4
*/
#include
#include
#include
#include "fpool.h"
#define MEM_POOL_DEBUG
#define DEFAULT_BASE_SIZE 4
#define DEFAULT_LINKS 4
#define DEFAULT_BLOCKS 4
#define DEFAULT_INCREMENT_LINKS 4
#define DEFAULT_INCREMENT_BLOCKS 4
#define ALIGN(ADD, SIZE) (((ADD) + ((SIZE) - 1)) & ~((SIZE) - 1))
/* 声明内存块, 前向引用 */
typedef struct _mem_block mem_block_t;
/* 内存节点指针 */
typedef union _mem_node
{
mem_block_t *b_next; /* 指向下一块内存节点 */
char data[1]; /* 内存节点首地址 */
}mem_node_t;
/* 内存块 */
struct _mem_block
{
short index; /* 内存链索引, mem_free 的时候有用 */
mem_node_t n_node; /* 内存节点 */
char pad[2];
};
/* 内存链 */
typedef struct _mem_link
{
struct _mem_link *l_next; /* 指向下一条内存链 */
short index; /* 内存链索引 */
short blocks; /* 内存链内存块数 */
short free_blocks; /* 内存链空闲内存块数 */
char pad[2];
mem_block_t *b_head; /* 内存链首内存块 */
}mem_link_t;
/* 内存池 */
typedef struct _mem_pool
{
short links; /* 内存链数 */
short base_size; /* 内存节点为base_size的倍数 */
mem_link_t *l_head; /* 首内存链 */
mem_link_t *l_tail; /* 尾内存链 */
}mem_pool_t;
static mem_pool_t mem_pool;
/* add new memory links to our memory pool */
static int add_mem_link(int links);
/* add new memory blocks to our memory link */
static int add_mem_block(mem_link_t *link, int blocks);
/*
* @base_size: 节点大小单位
* @links: 内存链条数
*/
int mem_pool_init(int base_size, int links)
{
if(base_size <= 0)
{
base_size = DEFAULT_BASE_SIZE;
}
else
{
/* base_size 为 4 的倍数 */
base_size = ALIGN(base_size, DEFAULT_BASE_SIZE);
}
if(links <= 0)
{
links = DEFAULT_LINKS;
}
/* initiate mem_pool */
memset(&mem_pool, 0, sizeof(mem_pool));
mem_pool.base_size = base_size;
/* add links into the memory pool */
if(!add_mem_link(links))
{
fprintf(stderr, "mem_pool_init::add_mem_link error\n");
return 0;
}
return 1;
}
void mem_pool_destroy(void)
{
mem_link_t *cur_l;
mem_block_t *cur_b;
cur_l = mem_pool.l_head;
while(cur_l)
{/* 释放内存链 */
mem_pool.l_head = mem_pool.l_head->l_next; /* 指向下一条内存链 */
cur_b = cur_l->b_head;
while(cur_b)
{/* 释放所有内存块 */
cur_l->b_head = cur_l->b_head->n_node.b_next; /* 指向下个内存块 */
free(cur_b);
cur_b = cur_l->b_head;
}
cur_l = mem_pool.l_head;
}
memset(&mem_pool, 0, sizeof(mem_pool_t));
}
void print_mem_pool_info(void)
{
int i;
mem_link_t *cur_l = NULL;
mem_block_t *cur_b = NULL;
cur_l = mem_pool.l_head;
if(NULL == cur_l)
{
printf("/nmemory pool is not exist!\n");
return;
}
/* memory pool info */
printf("/n/************** Memory pool information **************/\n");
#ifdef MEM_POOL_DEBUG
printf("sizeof(mem_node_t) : %d\n", sizeof(mem_node_t));
printf("sizeof(mem_block_t) : %d\n", sizeof(mem_block_t));
printf("sizeof(mem_link_t) : %d\n", sizeof(mem_link_t));
printf("sizeof(mem_pool_t) : %d\n", sizeof(mem_pool_t));
#endif
printf("links : %d\n", mem_pool.links);
printf("base_size : %d\n", mem_pool.base_size);
printf("link head pointer : %x(%d)\n", (int)mem_pool.l_head, (int)mem_pool.l_head);
printf("link tail pointer : %x(%d)\n", (int)mem_pool.l_tail, (int)mem_pool.l_tail);
while(cur_l)
{/* 打印内存链 */
printf("/n#### memory link %d ####\n", cur_l->index);
printf("blocks : %d\n", cur_l->blocks);
printf("free blocks : %d\n", cur_l->free_blocks);
printf("block size : %d\n", cur_l->index * mem_pool.base_size);
printf("block head pointer : %x(%d)\n", (int)cur_l->b_head, (int)cur_l->b_head);
cur_b = cur_l->b_head;
i = 0;
while(cur_b)
{
printf("memory block %d : %x(%d)\n", i++, (int)cur_b, (int)cur_b);
cur_b = cur_b->n_node.b_next;
}
cur_l = cur_l->l_next;
}
printf("/*****************************************************/\n");
}
void *mem_malloc(int size)
{
int align_size = ALIGN(size, mem_pool.base_size);
int index = align_size / mem_pool.base_size - 1;
mem_link_t *cur_l = mem_pool.l_head;
mem_block_t *cur_b = NULL;
mem_node_t *cur_n = NULL;
int i;
short *p_index;
if(index >= mem_pool.links)
{
printf("no such size(%d) memory block!\n", align_size);
return NULL;
}
/* go to the right link */
for(i = 0; i < index; ++i)
{
cur_l = cur_l->l_next;
}
if(0 >= cur_l->free_blocks)
{/* no free blocks, expand memory link */
if(!add_mem_block(cur_l, DEFAULT_INCREMENT_BLOCKS))
{
fprintf(stderr, "mem_malloc::add_mem_block error\n");
return NULL;
}
}
/* get free block from block head pointer */
cur_b = cur_l->b_head;
cur_l->free_blocks--;
/* modify memory link node head pointer */
cur_l->b_head = cur_l->b_head->n_node.b_next;
p_index = (short *)cur_b;
/* 记录索引, 便于 mem_free 找到正确的内存链 */
*p_index = cur_l->index;
++p_index;
cur_n = (mem_node_t *)p_index;
return (void *)&(cur_n->data[0]);
}
void mem_free(void *ptr)
{
short *p_index = (short *)ptr;
mem_link_t *cur_l = mem_pool.l_head;
mem_block_t *cur_b = NULL;
int i;
--p_index;
/* go to the right link */
for(i = 0; i < *p_index; ++i)
{
cur_l = cur_l->l_next;
}
cur_b = (mem_block_t *)p_index;
/* 内存链头部插入空闲内存块 */
cur_b->n_node.b_next = cur_l->b_head;
cur_l->b_head = cur_b;
cur_l->free_blocks++;
}
/* 返回成功添加的内存链条数 */
static int add_mem_link(int links)
{
mem_link_t *new_l = NULL;
int index = 0;
int i = links;
int cnt = 0;
/* 求得新添加链的索引 */
if(NULL == mem_pool.l_head)
{
index = 0;
}
else
{
index = mem_pool.l_tail->index + 1;
}
while(i--)
{
if(NULL == (new_l = (mem_link_t *)malloc(sizeof(mem_link_t))))
{
fprintf(stderr, "add_mem_link::malloc mem_link_t error\n");
continue;
}
/* 初始化新内存链 */
memset(new_l, 0, sizeof(mem_link_t));
new_l->index = index++;
/* 新内存链加入内存池 */
if(NULL == mem_pool.l_head)
{
mem_pool.l_head = new_l;
mem_pool.l_tail = new_l;
}
else
{
mem_pool.l_tail->l_next = new_l;
mem_pool.l_tail = new_l;
}
mem_pool.links++;
++cnt;
if(!add_mem_block(new_l, DEFAULT_INCREMENT_BLOCKS))
{
fprintf(stderr, "add_mem_link::add_mem_block error\n");
}
}
return cnt;
}
static int add_mem_block(mem_link_t *link, int blocks)
{
mem_block_t *new_b = NULL;
int i = blocks;
int cnt = 0;
if(NULL == link)
{
fprintf(stderr, "memory link is NULL!\n");
return 0;
}
#ifdef MEM_POOL_DEBUG
printf("add_mem_block::block_size: %d\n", sizeof(short) + mem_pool.base_size * (link->index + 1));
#endif
while(i--)
{
if(NULL == (new_b = (mem_block_t *)malloc(sizeof(short) + mem_pool.base_size * (link->index + 1))))
{
fprintf(stderr, "add_mem_block::malloc mem_block_t error\n");
continue;
}
/* 初始化新内存块 */
memset(new_b, 0, sizeof(mem_block_t));
new_b->index = link->index;
/* 新内存块加入内存链 */
if(NULL == link->b_head)
{
link->b_head = new_b;
}
else
{
new_b->n_node.b_next = link->b_head;
link->b_head = new_b;
}
link->blocks++;
link->free_blocks++;
++cnt;
}
return cnt;
}
#include
#include
#include "fpool.h"
void mempool_test_index0(void)
{
int *t1 = (int *)mem_malloc(sizeof(int));
int *t2 = NULL;
int value = 3;
if(NULL == t1)
{
printf("mempool_test_index0:: mem_malloc t1 NULL\n");
return;
}
print_mem_pool_info();
if(NULL == (t2 = (int *)mem_malloc(sizeof(int))))
{
printf("mempool_test_index0:: mem_malloc t2 NULL\n");
return;
}
print_mem_pool_info();
*t1 = value;
printf("mempool_test01:: t1: %d\n", *t1);
*t1 *= *t1;
*t2 = *t1;
(*t2)++;
printf("mempool_test01:: t1: %d\n", *t1);
printf("mempool_test01:: t2: %d\n", *t2);
mem_free(t1);
t1 = NULL; /* 不要忘了, 否则若两指针同时指向一块内存会出问题 */
print_mem_pool_info();
mem_free(t2);
t2 = NULL;
print_mem_pool_info();
}
int main()
{
if(!mem_pool_init(0, 0))
{
return -1;
}
print_mem_pool_info();
mempool_test_index0();
mem_pool_destroy();
print_mem_pool_info();
return 0;
}
02.
/***********************mem_pool.h************************
*
* * author:bripengandre
* * modified by: LaoLiulaoliu
* * TODO: thread_safe, different model
*
* *********************************************************/
#ifndef _MEM_POOL_H_
#define _MEM_POOL_H_
#define BUF_SIZE 100
#define BASE_COUNT 10000
#define STEP_COUNT 1000
typedef union _mem_node
{
char buf[BUF_SIZE];
union _mem_node *next;
} mem_node_t, *pmem_node_t;
/* consider of the efficiency, node_cnt can be annotated */
/* used to store block information */
typedef struct _mem_block
{
mem_node_t *node_head;
mem_node_t *node_tail;
int node_cnt; /* node count */
struct _mem_block *next;
} mem_block_t, *pmem_block_t;
/* consider of the efficiency, block_cnt can be annotated */
/* used to store the pool information */
typedef struct _mem_pool
{
mem_block_t *block_head;
// mem_block_t *block_tail;
mem_node_t *free_head;
int block_cnt; /* block count */
int free_cnt; /* free node count; */
int base;
int step;
} mem_pool_t, *pmem_pool_t;
/* mem_pool will have at least base blocks, and will increase steps a time if needed */
int mem_pool_init(int base, int step);
void mem_pool_destroy(void);
void print_mem_pool_info(void);
/* since the block size is constant, this function need no input parameter */
void *mem_alloc(void);
void mem_free(void *ptr);
#endif /* _MEM_POOL_H */
/***********************mem_pool.c************************
*
* * author:bripengandre
* * modified by: LaoLiulaoliu
*
* *********************************************************/
#include
#include
#include
#include "mem_pool.h"
/* static functions are the mainly expense of cpu in memory pool */
/* add new memory block to our memory pool */
static int add_mem_block(int cnt);
/* init the new block */
static int mem_block_init(int cnt, mem_block_t *block);
/* init free_list of the new block */
static int free_list_init(const mem_block_t *block);
static mem_pool_t mem_pool;
int mem_pool_init(int base, int step)
{
if(base <= 0)
{
base = BASE_COUNT;
}
if(step <= 0)
{
step = STEP_COUNT;
}
/* initiate mem_pool */
memset( &mem_pool, 0, sizeof(mem_pool) );
mem_pool.base = base;
mem_pool.step = step;
/* add the base block(node of base count) into the memory pool */
if( !add_mem_block(base) )
{
fprintf(stderr, "mem_pool_init::add_mem_block error\n");
return 0;
}
return 1;
}
void mem_pool_destroy(void)
{
mem_block_t *prev_block, *cur_block;
prev_block = NULL;
cur_block = mem_pool.block_head;
while(cur_block != NULL)
{
prev_block = cur_block;
cur_block = cur_block->next;
/* mem_block_init() malloc once,so just free once of the head pointer */
free(prev_block->node_head);
free(prev_block);
}
memset( &mem_pool, 0, sizeof(mem_pool_t) );
}
void print_mem_pool_info(void)
{
int i;
mem_block_t *p;
if(mem_pool.block_head == NULL)
{
fprintf(stderr, "memory pool has not been created!\n");
return;
}
printf("***************memory pool information start*******************\n");
printf("base block size: %d\n", mem_pool.base);
printf("increasing block size: %d\n", mem_pool.step);
printf("block count: %d\n", mem_pool.block_cnt);
printf("current free node count: %d\n", mem_pool.free_cnt);
printf("the first block: %#x\n", mem_pool.block_head);
//printf("the last block: %#x\n", mem_pool.block_tail);
printf("the first free node: %#x\n\n", mem_pool.free_head);
for(p = mem_pool.block_head, i = 0; p != NULL; p = p->next, i++)
{
printf("-----------------block %d-----------------------\n", i+1);
printf("node count: %d\n", p->node_cnt);
printf("the first node: %#x\n", p->node_head);
printf("-------------------------------------------------\n");
}
printf("***************memory pool information end*********************\n\n");
}
void *mem_alloc(void)
{
mem_node_t *p;
/* no free node ready, attempt to allocate new free node */
if(mem_pool.free_head == NULL)
{
if( !add_mem_block(mem_pool.step) )
{
fprintf(stderr, "mem_alloc::add_mem_block error\n");
return NULL;
}
}
/* get free node from free_list */
p = mem_pool.free_head;
mem_pool.free_head = p->next;
/* decrease the free node count */
mem_pool.free_cnt--;
return p;
}
void mem_free(void *ptr)
{
if(ptr == NULL)
{
return;
}
/* return the node to free_list */
((mem_node_t *)ptr)->next = mem_pool.free_head;
mem_pool.free_head = ptr;
/* increase the free node count */
mem_pool.free_cnt++;
}
static int add_mem_block(int cnt)
{
mem_block_t *block;
if( (block = malloc(sizeof(mem_block_t))) == NULL )
{
fprintf(stderr, "mem_pool_init::malloc block error\n");
return 0;
}
if( !mem_block_init(cnt, block) )
{
fprintf(stderr, "mem_pool_init::mem_block_init error\n");
return 0;
}
/* insert the new block in the head */
/* for the first time, block->next == NULL */
block->next = mem_pool.block_head;
mem_pool.block_head = block;
// if(mem_pool.block_tail == NULL)
// {
// mem_pool.block_tail = block;
// }
/* insert the new block into the free list */
/* block->node_tail->next == NULL in these two situations of add_mem_block() */
block->node_tail->next = mem_pool.free_head;
mem_pool.free_head = block->node_head;
mem_pool.free_cnt += cnt;
/* increase the block count */
mem_pool.block_cnt++;
return 1;
}
static int mem_block_init(int cnt, mem_block_t *block)
{
size_t size;
mem_node_t *p;
if(block == NULL)
{
return 0;
}
size = cnt * sizeof(mem_node_t);
if( (p = malloc(size)) == NULL )
{
fprintf(stderr, "mem_pool_init::malloc node error\n");
return 0;
}
memset(p, 0, size);
memset(block, 0, sizeof(mem_block_t));
block->node_cnt = cnt;
block->node_head = p;
block->node_tail = p+cnt-1;
free_list_init(block);
return 1;
}
static int free_list_init(const mem_block_t *block)
{
mem_node_t *p, *end;
if(block == NULL)
{
return 0;
}
/* start initiating free list */
end = block->node_tail; /* block_cnt > 0 */
for(p = block->node_head; p < end; p++)
{
p->next = (p+1);
}
p->next = NULL; /* end->next = NULL */
return 1;
}
#include
#include
#include "mem_pool.h"
#define ALLOC_COUNT 10
void alloc_test(char *ptr[])
{
int i, j;
for(i = 0; i < ALLOC_COUNT; i++)
{
if( (ptr[i] = mem_alloc()) == NULL )
{
fprintf(stderr, "mem_alloc error\n");
return;
}
for(j = 0; j < ALLOC_COUNT; j++)
{
ptr[i][j] = 'a' + j;
}
}
for(i = 0; i < ALLOC_COUNT; i++)
{
for(j = 0; j < ALLOC_COUNT; j++)
{
printf("ptr[%d][%d]=%c ", i, j, ptr[i][j]);
}
fputc('\n', stdout);
}
}
int main(int argc, char *argv[])
{
int base, step;
char *ptr1[ALLOC_COUNT], *ptr2[ALLOC_COUNT];
switch(argc)
{
case 1:
base = 0; /* default count */
step = 0; /* default count */
break;
case 2:
base = atoi(argv[1]);
step = 0;
break;
case 3:
base = atoi(argv[1]);
step = atoi(argv[2]);
break;
default:
fprintf(stderr, "Usage: %s [ [step]]\n", argv[0]);
break;
}
if( !mem_pool_init(base, step) )
{
fprintf(stderr, "mem_pool_init error\n");
return 1;
}
print_mem_pool_info();
alloc_test(ptr1);
print_mem_pool_info();
//mem_free(ptr1[5]);
print_mem_pool_info();
alloc_test(ptr2);
print_mem_pool_info();
mem_pool_destroy();
/* once again */
if( !mem_pool_init(base, step) )
{
fprintf(stderr, "mem_pool_init error\n");
return 1;
}
print_mem_pool_info();
alloc_test(ptr1);
print_mem_pool_info();
mem_free(ptr1[5]);
print_mem_pool_info();
alloc_test(ptr2);
print_mem_pool_info();
mem_pool_destroy();
return 0;
}
03.
#ifndef MEMORYPOOL_H_INCLUDED
#define MEMORYPOOL_H_INCLUDED
#include
#include
#include
typedef struct Memorypool
{
int mempool_size;
int memory_size;//block_size + sizeof(manager information) = mem_size
int block_size;
int total_memory_cnt;
int used_memory_cnt;
int auto_extend;
struct Memory* free_list;
struct Memory* used_list;
}memorypool;
typedef struct Memory
{
int memory_size;
int block_size;
struct Memory* prev;
struct Memory* next;
struct Memorypool* mp;
char* block;
}memory;
memorypool* memorypool_create(int block_request_size, int memory_init_quantity, _Bool memory_extend);
char* memory_malloc(memorypool* mp,int data_size);
int memorypool_info_get(memorypool* mp);
int memory_free(char** p_bk);
int memorypool_destroy(memorypool* mp);
memory* memory_creat(int memory_size, memorypool* mp);
#endif // MEMORYPOOL_H_INCLUDED
#include "memorypool.h"
memorypool* memorypool_create(int block_request_size, int memory_init_quantity, _Bool memory_extend)
{//請求最大極限,記憶池數量=>記憶池大小(基底*數量),
memorypool* mp = NULL;
mp = (memorypool*)malloc(sizeof(memorypool));
memset(mp, 0, sizeof(memorypool));
mp->block_size = block_request_size;
mp->memory_size = block_request_size + sizeof(memory);
mp->auto_extend = memory_extend;
for (int i = memory_init_quantity; i > 0; i--)
{
memory* mm = NULL;
mm = memory_creat(mp->memory_size , mp);
}
return mp;
}
char* memory_malloc(memorypool* mp, int data_size)
{
memory* p_memory = NULL;
if (mp->block_size < data_size)
{
return NULL;
}
if (NULL == mp->free_list)
{
if (mp->auto_extend == 1)
memory_creat(mp->memory_size, mp);
else
return NULL;
}
p_memory = mp->free_list;
mp->free_list = mp->free_list->next;
p_memory->next = NULL;
if (mp->used_list)
{
mp->used_list->prev->next = p_memory;
p_memory->prev = mp->used_list->prev;
}
else
{
mp->used_list = p_memory;
}
p_memory->next = mp->used_list;
mp->used_list->prev = p_memory;
mp->used_list = p_memory;
mp->used_memory_cnt += 1;
return p_memory->block;
}
int memorypool_info_get(memorypool* mp)
{
printf("current mempool_size:%d\n\
current memory_size:%d\n\
current block_size:%d\n\
total_memory_cnt:%d\nused_memory_cnt:%d\n",mp->mempool_size,mp->memory_size,mp->block_size, \
mp->total_memory_cnt,mp->used_memory_cnt);
return 0;
}
int memory_free(char** p_bk)
{
memory* p_memory = (memory* )(*p_bk - sizeof(memory)/(sizeof(char)));//正确
p_memory->next->prev = p_memory->prev;
p_memory->prev->next = p_memory->next;
p_memory->next = NULL;
p_memory->prev = NULL;
if (p_memory->mp->used_memory_cnt == 1)
{
p_memory->mp->used_list = NULL;
}
p_memory->next = p_memory->mp->free_list;
p_memory->mp->free_list = p_memory;
p_memory->mp->used_memory_cnt -= 1;
*p_bk = NULL;
return 0;
}
int memorypool_destroy(memorypool* mp)
{
memory* mm = NULL;
if (mp->free_list)
{
mm = mp->free_list;
mp->free_list = mp->free_list->next;
free(mm);
mm = NULL;
}
if (mp->used_list)
{
mp->used_list->prev->next = NULL;
mm = mp->used_list;
mp->used_list = mp->used_list->next;
free(mm);
mm = NULL;
}
free(mp);
return 0;
}
memory* memory_creat(int memory_size, memorypool* mp)
{
memory* mm = NULL;
char* bk = NULL;
char* memory_start = (char*)malloc(memory_size);
memset(memory_start, 0, memory_size);
mm = (memory*)memory_start;
memset(mm, 0, sizeof(memory));
bk = memory_start - sizeof(memory);//错误
bk =memory_start +sizeof(memory)/(sizeof(char));//正确
mm->memory_size = memory_size;
mm->block_size = memory_size - sizeof(memory);
mm->mp = mp;
mm->block = bk;
mm->next = mp->free_list;
mp->free_list = mm;
mp->total_memory_cnt += 1;
mp->mempool_size += mp->memory_size;
return mm;
}
#include
#include
#include
#include "memorypool.h"
void print_info_line(char *data)
{
printf("%s---%d\t%s\n",__FILE__, __LINE__,data);
}
int main()
{
memorypool* mp = NULL;
int memory_init_quantity = 5;
_Bool memory_extend = 1;
int block_request_size =1024;
time_t start = 0;
time_t end = 0;
int count = 0;
mp = memorypool_create(block_request_size, memory_init_quantity, memory_extend);//1024,5,1
print_info_line("memorypool_create");
memorypool_info_get(mp);
struct test
{
int a;
int b;
};
struct test* p_data;
/*
start = time(NULL);
int i=10;
while (i>0)
{
p_data = (struct test*)memory_malloc(mp, sizeof(struct test));
//p_data = (struct test*)malloc(sizeof(struct test));
memorypool_info_get(mp);
p_data->a = 100;
memory_free((char**)&p_data);
memorypool_info_get(mp);
//free(p_data);
end = time(NULL);
count += 1;
if (end == (start + 300))
{
printf("%d", count);
break;
}
i--;
}
*/
p_data = (struct test*)memory_malloc(mp, sizeof(struct test));
p_data->a = 100;
p_data->b = 200;
int Sum = p_data->a + p_data->b;
printf("Sum=%d\n",Sum);
print_info_line("memory_malloc");
memorypool_info_get(mp);
memory_free((char**)&p_data);
print_info_line("memory_free");
memorypool_info_get(mp);
memorypool_destroy(mp);
print_info_line("memorypool_destroy");
return 0;
}
寫了
5860316篇文章,獲得
23313次喜歡