Write malloc by yourself and malloc by yourself

Source: Internet
Author: User

Write malloc by yourself and malloc by yourself

Next, I wrote a blog post about malloc and sbrk in Process Memory Management in Linux. Let's talk about how to write the implementation details of the malloc function by yourself.

If you read the previous article, you should know the memory management of the process and the implementation principle of the malloc function. In fact, the space allocated by the malloc function is obtained by using the sbrk function, but this function should not be called every time the user calls malloc, which is too overhead and unnecessary. Therefore, you need to add memory allocation, release, merge, and other operations in malloc.

The first thing to note is that each time the space applied through the sbrk function is continuous, the memory space to be managed by the malloc function is also consecutive. However, as users release and apply for multiple times, some of these spaces are in the user Usage Status and some are in the user release status:


Metadata Design

As shown in, in each section of space, in addition to the space requested by the user, you also need a part of meta-data to manage the space. In my program, I set the size of this Part to 8 bytes. These 8 bytes not only need to store the size of the segment space, but also need to indicate the starting position of the next segment space. In my design, the first four bytes are used to indicate the length of the segment space. The length includes not only the length of the data Segment but also the 8 bytes of meta-data; the last four bytes indicate whether the segment space is in use or idle state.

Another important thing to note is alignment, because alignment allocation consumes less space and facilitates later management. In this program design, I use 8-byte alignment. For example, if a user applies for a 99-byte space, the space actually allocated to the user should be a factor greater than the minimum 8 of 99, that is, 104, in addition, 8 bytes of meta-data need to be added, so the total applied space is 112 bytes.

In other words, do not use division when calculating the size of the space actually allocated to the user. A more efficient way is to use shift operations. For example, if you need to apply for a size space of several bytes, you can use (size-1)> 3) <3) to calculate the actually allocated space) + 8 + 8.

In addition, it is required that sbrk should be used at least 8192 bytes at a time.

13 # define SPACE_IN_USE 0 // user usage 14 # define SPACE_AVAILABLE 1 // idle status 15 # define MINIMUM_SBRK_SPACE 8192 16 17 # define align8 (size) \ 18 size = (size-1)> 3) <3) + 8 25 void * free_list_head; // static variable, indicating the start address of the dynamic space

Another function of maintaining the space linked list malloc is to maintain the space opened through the sbrk. Through the metadata described above, it is not difficult to find that the memory space is actually a linked list, this linked list records each space, including the space that the user is using or is not using. To maintain this linked list, two function functions are required:
Void * free_list_begin (); // return the starting address of the first idle space. If no, return NULLvoid * free_list_next (void * node); // return the last space of the node, NULL <pre name = "code" class = "cpp"> void * <pre name = "code" class = "cpp"> free_list_begin
() 11 {12 // if the head is null 13 if (! Free_list_head) 14 {15 return NULL; 16} 17 else 18 {19 void * tmp = free_list_head; 20 while (tmp! = (Void *) sbrk (0) 21 {22 int * size = (int *) tmp; 23 int * flag = (int *) (tmp + 4 ); // the flag to indicate whether this space is in use 24 if (* flag = SPACE_AVAILABLE) 25 {26 return tmp; 27} 28 else 29 {30 tmp + = * size; 31} 32} 33 return NULL; 34} 35} 37 void * free_list_next (void * node) 38 {39 if (! Free_list_head |! Node) 40 {41 return NULL; 42} 43 44 if (node <free_list_head | node> sbrk (0) 45 {46 printf ("illeagal address \ n "); 47 return NULL; 48} 49 int flag = 0; 50 void * tmp = free_list_head; 51 while (tmp <sbrk (0) 52 {53 int * size = (int *) tmp; 54 if (tmp = node) 55 {56 tmp + = * size; 57 break; 58} 59 tmp + = * size; 60 61} 62 if (tmp = sbrk (0) 63 {64 return NULL; 65} 66 while (tmp <sbrk (0 )) 67 {68 int * size = (int *) tmp; 69 int * flag = (int *) (tmp + 4); 70 if (* flag) = SPACE_AVAILABLE) 71 {72 return tmp; 73} 74 tmp + = (* size); 75} 76 return NULL; 77}
 
 


My_malloc and my_free Functions
 79 void*  my_malloc_new(size_t size) 80 { 81     size_t new_size = size; 82     align8(new_size); 83     new_size += 8; 84     if(new_size >=  MINIMUM_SBRK_SPACE) 85     { 86         void* res = sbrk(new_size); 87         if((void*)-1 == res) 88         { 89             printf("error occured when allocation space\n"); 90             return NULL; 91         } 92         *((int*)res) = new_size; 93         *((int*)(res + 4)) = SPACE_IN_USE; 94         return res; 95     } 96     else 97     { 98         size_t gap = MINIMUM_SBRK_SPACE - new_size; 99         align8(gap);100         gap+=8;101         void* res = sbrk(gap + new_size);102         if((void*)-1 == res)103         {104             printf("error occured when allocating space\n");105             return NULL;106         }107         *((int*)res) = new_size;108         *((int*)(res + 4)) = SPACE_IN_USE;109 110         res += new_size;111         *((int*)res) = gap;112         *((int*)(res + 4)) = SPACE_AVAILABLE;113         res -= new_size;114         return res;115     }116 117 118 }120 void* my_malloc(size_t size)121 {122     //create a new node123     if(NULL == free_list_begin())124     {125         void* res = my_malloc_new(size);126         free_list_head = res;127         return res + 8;128     }129     else130     {131         void* tmp = free_list_begin();132 133         size_t new_size = size;134         align8(new_size);135         new_size += 8;136 137 138         while(tmp != NULL)139         {140             int cur_size = *((int*)tmp);141             if(cur_size >= new_size)142             {143                 if(cur_size >= new_size + 12)144                 {145                     *((int*)tmp) = new_size;146                     *((int*)(tmp + 4)) = SPACE_IN_USE;147 148                     void* new_tmp = tmp + new_size;149                     *((int*)(new_tmp)) = cur_size - new_size;150                     *((int*)(new_tmp + 4)) = SPACE_AVAILABLE;151                 }152                 else153                 {154                     *((int*)(tmp + 4)) = SPACE_IN_USE;155                 }156                 157                 return tmp + 8;158             }159             tmp = free_list_next(tmp);160         }161         162         void* res = my_malloc_new(size);163         return res + 8;164     }165 }167 void my_free(void *ptr)168 {169     if(ptr < free_list_head || sbrk(0) < ptr)170     {171         printf("illegal pointer\n");172         return;173     }174     printf("free ptr:%p\n", ptr);175     int* flag = (int*)(ptr - 4);176     *flag = SPACE_AVAILABLE;177     return;178 }

The my_free function is simple, that is, to set the symbol position in meta-data to SPACE_AVAILABLE. The logic of my_malloc is to traverse the entire idle space through free_list_begin () and free_list_next (). If there is enough space, allocate it. If not, re-allocate it using sbrk.
Coalesce_free_list another problem to be aware of is that when the user uses my_malloc and my_free for multiple times, there will be a fragmentation problem, that is, there are multiple consecutive, free space, the coalesce_free_list function is used to merge these consecutive idle spaces into one space.
180 void coalesce_free_list()181 {182     void *first, *second, *tail;183     first = free_list_begin();184     int tmp_size = *((int*)first);185     int size = tmp_size;186     second = first + tmp_size;187     tail = sbrk(0);188 189     while(second < tail && first < tail)190     {191         while(second < tail && *((int*)(second + 4)) == SPACE_AVAILABLE )192         {193             tmp_size = *((int*)second);194             size += tmp_size;195             second += tmp_size;196         }197         *((int*)first) = size;198         first = second;199         while(first < tail && *((int*)(first + 4)) == SPACE_IN_USE )200         {201             first += *((int*)first);202         }203         if(first == tail)204         {205             return;206         }207         else208         {209             size = *((int*)first);210             second = first + size;211         }212     }213     return;214 }

All right, the entire code is finished. I have already put the code on csdn. You can download it: Click to open the link.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.