C中內存分配及管理小結 中英文對照 (Summary of C memory allocation and management Chinese&Englise)

Summary: C memory allocation and management 

The other day when I do some modification with BioHDF, I met the error 

        glibc detected   ***free(): invalid next size(normal),

because function free released the local pointer not allocated memory by malloc, and the use of free is needless. In the following sections, we will talk about the C memory allocation and management.

1.Reference of  malloc/free  

malloc:  

           Use needs include header file:          #include  <stdlib.h>

     Function prototype:           void* malloc(unsigned int size);

//code1
#inlcude <stdlib.h>
#inlcude <stdio.h>

int main()
{
      int* p = (int*) malloc(sizeof(int));
      if (p == NULL) {
	return 0;
	}
      *p = 10000;
      printf("p = %p, *p = %d\n", p, *p );

        free(p);
        printf("p = %p, *p = %d\n", p, *p);

         return 0;
}


 

    If you write int* p = malloc(sizeof(int)) , there will have a error because the compiler can't give void* type to int* type. You have to use (int*) to cast type.

    If you write int* p = malloc(1), it can pass the compiling, but actually it just obtain 1 Byte memory. When you store an integer in *p, the test 3 Bytes will be homeless, so , they will live in the neighbourhood's house which results in replacing the neighbourhood house original data. Horrible!

    If malloc failed, it will return NULL.

    In C++, we use new/delet and new[]/delete[] instead.

   free:

           Use needs include header file:         #include  <stdlib.h>

         Function prototype:           void free(void* FirstByte);

      Free() has to release all data type memory, so the parameter type is void*. Any type pointer can use as void* type. 

   

Tips: 1.After malloc, you had better check whether success or not.

        2.When you don't need the allocated memory any more, please free it; after free, give value NULL to the memory pointer to avoid post-use. 

        3.The malloc() and free() should be called in pairs. If you malloc but don't free, there will have memory leak. If you don't malloc but free, there will have an error, like me at the begin of this blog.

        4.Using malloc, you had better cast return value type to what type you need.        

2. Deeper mechanism

        (1) Where does the  memory by malloc() come from?

                      Ans: Befor we answer this question, we must learn something about C program  memory management.   The C program consists of 4 logical parts.

                        A. Executive source code.

                        B. Static data.

                                Executive source code and static data belongs to fixed region in memory.

                        C. Stack region

                                Stack region stores the parameter values of function, local variable, etc. Stack region is allocated  and released by compiler automatically in execution and after execution.

                        D. Heap region

                                Heap region stores dynamic allocation memory, and it is allocated and released by program itselt by functions like malloc, realloc, calloc and free. When execution exit, the heap region will be retrieved by Operating System. But in the execution, if you allocate memory and don't free, there will have a memory leak and if it in a large loop, the system will corrupt.

            So in code1, the pointer p is stored in stack region because it is a local pointer variable, and the memory p points at is stored in heap region because it is dynamically allocated.

        (2). What exactly does free(p) free?

                    Ans: Function free() frees the memory pointer p points at, not the pointer p. The pointer p is a local variable, it will be freed  when it is out of  Action Scope or the exit of execution. After free, the pointer p still points at the memory space but what in it is not the previous data, so p becomes the wild pointer, and we had better give NULL value to the p.

//code2
#include <stdlib.h>
#inlcude <stdio.h>

int* func()
{
      int a = 10000;
      int*  p = &a;
      printf("In func: p = %p, *p = %d\n", p, *p);
      
       return p;
}

int main()
{
     int* p1;
     p1 = func();

     printf("In main: p = %p, *p = %d\n", p, *p);
      
      return 0;    
}


          In compiling, it comes  the warning:


In function 'func':
warning: function returns address of local variable.

          It means that  function 'func' returns a local variable address. As we know, after the 'func' exits the execution,  the local variable in this Action Scope will be released.

 

//code3
#include <stdlib.h>
#inlcude <stdio.h>

int* func()
{
      int*  p = (int*)malloc(sizeof(int));
      *p = 10000;
      printf("In func: p = %p, *p = %d\n", p, *p);
      
       return p;
}

int main()
{
     int* p1;
     p1 = func();

     printf("In main: p = %p, *p = %d\n", p, *p);
      
      return 0;    
}


 

        You can differ the difference between the code2 and code3, and you can understand my intention. To my surprise, the execution result depends on machine or maybe complier difference. You can run them by yourselt and give feedback to me.

      

 

     (3). Mechanism  

                What the malloc() actually do is

                            A. Linking the available memory block as a long Chain Table.

                            B. Searching a large enough block which  meets the user's demand.

                            C. Separating the selected block into two parts: one is as large as the user's call, the other is left space and link it to the Chain Table again for post-use(if exist).

                            D.After many times allocation, the memory block becomes increasingly small, so if this time needed memory by user is larger than all blocks in the Chain Table, the malloc() will require time-delay, and settle and combine to get a large enough block.

                   In fact, the returned memory size by malloc()  is larger than user's call, because there must have some memory to store the data that manage this memory block such that whether available or not, what size is it. The management data is the structure:

 

   struct  mem_control_block {
        int is_available;
        int size;
};



      When calling malloc(), malloc() will return the address behind the struct end which points at the free memory that user can directly use, so the struct is invisible for users. When calling free(), the free() recedes the sizeof(mem_control_block) and the pointer points at the begin of the struct mem_control_block. You can see that in the realization of free() code:

 

void free(void* firstByte)
{
     struct mem_control_block *mcb;
     mcb = firstByte - sizeof(struct mem_control_block);
     mcb->is_available = 1;
     
     return;
}

         

          We also can say that the memory allocated is actually not released by free() itselt, it may be released by the Operating System, what free() does is to tell the Operating System which block can be released and it's first Byte. 

       The memory allocation realization is more compicated, and there are some popular implemetation of this functionality. The malloc() is the standard C library implementation. In addition to malloc(), there also are Doug Lea Malloc, BSD Malloc, Hoard, etc. These memory allocation implementations have their own good qualites and shortcommings, because the memory allocation implementation must consider a lot of factors such that allocation speed, retrieve speed, bookkeeping cost, and so on. According to these factors, their algorithms are also different with each other.

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章