STL内存管理的C实现

简介: //STL 内存管理器的C实现 #include stdio.h> #include stdlib.h> #define __ALIGN 8    //小型区块上调边界 #define __MAX_BYTES 128    //小型区块大小的上限 ...
  1. //STL 内存管理器的C实现

  2. #include stdio.h>
  3. #include stdlib.h>

  4. #define __ALIGN 8    //小型区块上调边界
  5. #define __MAX_BYTES 128    //小型区块大小的上限
  6. #define __NFREELISTS (__ALIGN/__MAX_BYTES)    //free-lists的个数

  7. typedef union obj{
  8.     union obj *free_list_link;
  9.     char client_data[1];
  10. }obj;
  11. obj *free_list[__NFREELISTS];
  12. char *start_free;    //mempool开始位置
  13. char *end_free;    //mempool结束位置
  14. size_t heapsize;

  15. size_t ROUND_UP(size_t bytes);
  16. size_t FREELIST_INDEX(size_t bytes);
  17. void *stl_malloc(size_t nbytes);
  18. void stl_free(void *p, size_t nbytes);
  19. void *refill(size_t n);
  20. char *chunk_alloc(size_t bytes, size_t *nobjs);


  21. int main(){
  22.     int len= 65;
  23.     void *ptr = stl_malloc(len);
  24.     printf("%p\n", ptr);
  25.     stl_free(ptr, len);
  26.     return 0;
  27. }

  28. //将bytes上调到__ALIGN的倍数
  29. size_t ROUND_UP(size_t bytes){
  30.     return ((bytes + __ALIGN - 1) & ~(__ALIGN - 1));
  31. }
  32. //返回bytes所对应的freelist索引号
  33. size_t FREELIST_INDEX(size_t bytes){
  34.     return ((bytes + __ALIGN - 1) / __ALIGN - 1);
  35. }
  36. void *stl_malloc(size_t nbytes){
  37.     if(nbytes > 128){
  38.         return malloc(nbytes);
  39.     }
  40.     obj **my_free_list;
  41.     obj *result;
  42.     my_free_list = free_list + FREELIST_INDEX(nbytes);
  43.     result = *my_free_list;
  44.     if(result == NULL){
  45.         void *r = refill(ROUND_UP(nbytes));
  46.         return r;
  47.     }
  48.     //取出空闲块
  49.     *my_free_list = result->free_list_link;
  50.     return result;
  51. }
  52. void stl_free(void *p, size_t nbytes){
  53.     obj *q = (obj *)p;
  54.     obj **my_free_list;
  55.     if(nbytes > (size_t)__MAX_BYTES){
  56.         free(p);
  57.         return;
  58.     }
  59.     my_free_list = free_list + FREELIST_INDEX(nbytes);
  60.     q->free_list_link = *my_free_list;
  61.     *my_free_list = q;
  62. }
  63. void *refill(size_t n){
  64.     //默认从内存池取得20个块,多个块构成一个chunk
  65.     size_t nobjs = 20;    //-结果参数
  66.     char *chunk = chunk_alloc(n, &nobjs);    
  67.     if(!chunk){
  68.         return NULL;
  69.     }
  70.     obj **my_free_list;
  71.     obj *result, *cur_obj, *next_obj;
  72.     int i;
  73.     //内存池空间告急仅返回一个块,则直接返回给用户
  74.     if(nobjs == 1){
  75.         return chunk;
  76.     }
  77.     //否则准备向free_list中纳入新的节点
  78.     my_free_list = free_list + FREELIST_INDEX(n);
  79.     //以下在chunk的连续空间上建立free_list
  80.     result = (obj *)chunk;    //此块返回给用户
  81.     *my_free_list = next_obj = (obj *)(chunk + n);
  82.     for(i = 1; ; i++){
  83.         cur_obj = next_obj;
  84.         next_obj = (obj *)((char *)next_obj + n);
  85.         if(nobjs - 1 == i){
  86.             cur_obj->free_list_link = NULL;
  87.             break;
  88.         }else{
  89.             cur_obj->free_list_link = next_obj;    
  90.         }
  91.     }
  92.     return result;
  93. }
  94. //从内存池取连续的块空间
  95. char *chunk_alloc(size_t bytes, size_t *nobjs){
  96.     char *result;
  97.     size_t total_bytes = bytes * (*nobjs);    //要求的字节数
  98.     size_t bytes_left = end_free - start_free;    //

  99.     //内存池空间宽裕
  100.     if(bytes_left >= total_bytes){
  101.         result = start_free;
  102.         start_free += total_bytes;
  103.         return result;
  104.     }else if(bytes_left >= bytes){
  105.         //不够分配全部的,但是还可以分配一个或多个块
  106.         *nobjs = bytes_left/bytes;
  107.         total_bytes = *nobjs * bytes;
  108.         result = start_free;
  109.         start_free += total_bytes;
  110.         return result;
  111.     }else{
  112.         //内存池黔驴技穷了,连一个块的空间都没有了
  113.         size_t bytes_to_get = 2 * total_bytes + ROUND_UP(heapsize >> 4);
  114.         if(bytes_left > 0){
  115.             //内存池中还有一些零头,先配给适当的free-list
  116.             obj **my_free_list = free_list + FREELIST_INDEX(bytes_left);
  117.             ((obj *)start_free)->free_list_link = *my_free_list;
  118.             *my_free_list = (obj *)start_free;
  119.         }
  120.         start_free = (char *)malloc(bytes_to_get);
  121.         if(start_free == NULL){
  122.             //看看更大块的free_list有无可用块
  123.             int i;
  124.             obj **my_free_list, *p;
  125.             for(i = bytes; i = __MAX_BYTES; i += __ALIGN){
  126.                 my_free_list = free_list + FREELIST_INDEX(i);
  127.                 p = *my_free_list;
  128.                 if(p){
  129.                     *my_free_list = p->free_list_link;
  130.                     start_free = (char *)p;
  131.                     end_free = start_free + i;
  132.                     //递归调用自己,按新的状态重新分配,并修正nobjs;
  133.                     return chunk_alloc(bytes, nobjs);
  134.                 }
  135.             }
  136.             //实在没有空间了
  137.             end_free = 0;
  138.             return NULL;
  139.         }
  140.         heapsize += bytes_to_get;
  141.         end_free = start_free + bytes_to_get;
  142.         return chunk_alloc(bytes, nobjs);
  143.     }
  144.     
  145. }
相关文章
|
8月前
|
存储 缓存 安全
C语言中的内存管理与优化技巧
C语言中的内存管理与优化技巧
215 0
|
存储 C语言 C++
31 C语言 - 内存管理
31 C语言 - 内存管理
57 0
|
2月前
|
存储 C语言 开发者
C 语言指针与内存管理
C语言中的指针与内存管理是编程的核心概念。指针用于存储变量的内存地址,实现数据的间接访问和操作;内存管理涉及动态分配(如malloc、free函数)和释放内存,确保程序高效运行并避免内存泄漏。掌握这两者对于编写高质量的C语言程序至关重要。
77 11
|
2月前
|
安全 Java 程序员
Zig 内存管理
Zig 内存管理
51 1
|
4月前
|
存储 大数据 C语言
C语言 内存管理
本文详细介绍了内存管理和相关操作函数。首先讲解了进程与程序的区别及进程空间的概念,接着深入探讨了栈内存和堆内存的特点、大小及其管理方法。在堆内存部分,具体分析了 `malloc()`、`calloc()`、`realloc()` 和 `free()` 等函数的功能和用法。最后介绍了 `memcpy`、`memmove`、`memcmp`、`memchr` 和 `memset` 等内存操作函数,并提供了示例代码。通过这些内容,读者可以全面了解内存管理的基本原理和实践技巧。
|
8月前
|
程序员 编译器 C语言
C语言中如何进行内存管理
C语言中如何进行内存管理
108 0
|
8月前
|
C++ 容器
【C++】程序题( STL标准模板库)
【C++】程序题( STL标准模板库)
【C++】程序题( STL标准模板库)
|
8月前
|
存储 安全 程序员
C语言内存管理
C语言内存管理
41 0
|
算法 Linux 编译器
【c++ • STL】初步认识什么是 STL 标准库
【c++ • STL】初步认识什么是 STL 标准库
154 1
|
存储 程序员 C语言
C语言编程—内存管理
C语言中的动态内存管理。C语言为内存的分配和管理提供了几个函数。这些函数可以在 <stdlib.h> 头文件中找到。 在C语言中,内存是通过指针变量来管理的。指针是一个变量,它存储了一个内存地址,这个内存地址可以指向任何数据类型的变量,包括整数、浮点数、字符和数组等。C语言提供了一些函数和运算符,使得程序员可以对内存进行操作,包括分配、释放、移动和复制等。 注意:void * 类型表示未确定类型的指针。C、C++ 规定 void * 类型可以通过类型转换强制转换为任何其它类型的指针。 动态分配内存 编程时,如果您预先知道数组的大小,那么定义数组时就比较容易。例如,一个存储人名的数组,它
125 0