Implementation code based on malloc and free function and its analysis _c language

Source: Internet
Author: User
Tags data structures

The malloc and free functions for memory management should be familiar to programmers using the C language. Some time ago I heard that some IT companies to "achieve a simple function of the malloc" as an interview question, just recently in the review K&r, above introduced, so took some time to study carefully. After all, the topic is secondary, understand the realization of ideas, upgrade technology is the main. This article is mainly about malloc and free implementation of the introduction of ideas, the blue part of the text is in the personal thinking of the core of things; In addition, for the description of the code, there are some k&r on the interpretation of the use of green highlight.

Before studying the implementation of chapter eighth fifth of K&r, it may be useful to take a look at the Alloc/afree implementation of its fifth chapter fourth, although the main purpose of this code is to show address operations.

Copy Code code as follows:

Alloc implementation

#define ALLOCSIZE 10000
static Char allocbuf[allocsize]; /*storage for alloc*/
static char *ALLOCP = ALLOCBUF; /*next Free position*/

char *alloc (int n)
{
if (ALLOCBUF+ALLOCSIZE-ALLOCP >= N) {
ALLOCP + = n;
return alloc-n;
} else
return 0;
}

void Afree (char *p)
{
if (P >= allocbuf && p<allocbuf + allocsize)
ALLOCP = p;
}

  The disadvantage of this simple implementation :

1. As a representative of the memory resources of the ALLOCBUF, in fact, is the allocation of good, there may be waste.

2. The order of distribution and release is similar to the stack, which is "LIFO," which can cause an exception if not in order.

Although this implementation is relatively simple, but still provides a way of thinking. If these two shortcomings can be eliminated, it will be possible to achieve a more ideal malloc/free.

Relying solely on address operations is a reason to limit the flexibility of allocation recycling, requiring that the used and unused portions must be separated into two contiguous areas by an address. In order to allow the two regions to cross each other, and even include some unallocated address space, it is necessary to use pointers to connect the same memory space to form a linked list, so as to deal with a series of memory space with a discontinuous address. But why is it only connected to free space without connecting to the space in use? This may not be thought out of the intuition of the analogy in the diagram, which is simple because it is not necessary. The former are linked in order to be able to traverse all the free space while the memory is allocated, and to reinsert the used space when it is used to reclaim it. As for the space in use, because we already know their address when allocating space, we can tell free () directly from the recycle, and do not need to traverse like malloc ().

Now that the list is mentioned, people who might know a little about the data structure immediately write a struct to represent an area of memory that contains a pointer to the next memory area, but what about the other members of the struct? as an area of memory to be allocated, the size is variable, and it is obviously not appropriate to declare it as a struct member; If you declare it as a pointer to a different area, it does not seem to match the visual representation above. (Of course, this is achievable, too. It seems to be between the two in the above, the management structure and the actual allocation of space split, at the end of the text I will discuss the implementation of this approach is so that the control structure and free space is still separated, but keep them in the memory of the adjacent address, form the following figure, and it is by this feature that we can position the corresponding memory region by using the pointer operation on the control structure pointer:

  

Correspondingly, the control information is defined as header:

Copy Code code as follows:

typedef long ALIGN;/*FOR alignment to long boundary*/
Union Header {
struct {
Union header *ptr; /*next block if on free list*/
unsigned size; /*size of this block*/
} s;
Align x;
};

typedef union Header Header;

   The reason for using union instead of using struct directly is for address alignment. Here is a long alignment, and the Union X will never be used.

In this way, the main job of malloc is to manage these headers and subsequent memory blocks.

Copy Code code as follows:

malloc ()

static Header base;
static Header *freep = NULL;

void *malloc (unsigned nbytes)
{
Header *p, *PREVP;
unsigned nunits;
Nunits = (nbytes+sizeof (header)-1)/sizeof (header) + 1;
if ((Prevp = freep) = = NULL) {/* No free list */
Base.s.ptr = Freep = PREVP = &base;
base.s.size = 0;
}
for (p = prevp->s.ptr;;p REVP = p, p= p->s.ptr) {
if (p->s.size >= nunits) {/* big enough * *
if (p->s.size = = nunits)/* exactly *
Prevp->s.ptr = p->s.ptr;
else {
P->s.size-= nunits;
p + + p->s.size;
P->s.size = nunits;
}
Freep = PREVP;
Return (void*) (p+1);
}
if (p== freep)/* Wrapped around free list * *
if (p = Morecore (nunits)) = = NULL)
return NULL; /* None Left */
}
}


   The actual allocated space is an integer multiple of the header size, and a space with a header size is used to place the header.But intuitively this is not nunits = (nbytes+sizeof (header)-1)/sizeof (header) + 1 ah? Nbytes+sizeof (header)/sizeof (header) +1 not exactly? In fact, if you use the latter, the nbytes+sizeof (header)%sizeof (header) = 0 o'clock, and the allocation of more than one Header size space,So you have to subtract 1 from the parentheses to meet your requirements.

malloc () First call establishes a degenerate linked list base, only one size is 0 of the space and points to it itself. Freep is used to identify an element of an idle list, changes can occur each time a lookup occurs; the middle lookup and allocation process is a basic list operation that calls Morecore () to get more memory space when there is no suitable size of free space in the free list; the last return value is the first address of the free space. The address after the header, which is consistent with the library function.

Copy Code code as follows:

Morecore ()

#define NALLOC 1024/* Minimum #units to request * *
Static Header *morecore (unsigned nu)
{
Char *CP;
Header *up;
if (Nu < Nalloc)
Nu = nalloc;
cp = SBRK (NU * sizeof (Header));
if (cp = = (char *)-1)/* No space at all*/
return NULL;
Up = (Header *) CP;
Up->s.size = Nu;
Free ((void *) (up+1));
return freep;
}


Morecore () request more free space from the system and join. Because of the call to SBRK (),System overhead is relatively large, in order to avoid morecore () itself the number of calls, set a nalloc, if each application space is less than nalloc, apply for nalloc size of space, make subsequent malloc () do not need to call Morecore () every time.For SBRK (), the following will be covered.

Here's an amazing place:malloc () called Morecore (), and Morecore () called Free ()! The first time I see it, it may feel incredible, because according to inertia thinking, malloc () and free () seems to be separated from each other, their respective duties ah? But please think again,free () is to expand the idle list, and malloc () when the free list is not enough, from the system to apply to more memory space, but also first to convert them into a part of the free list, and then make use of. In this way, malloc () Call free () to complete the work of the following is also logical. According to this idea, the following is the implementation of free (). Before that, there are several details of Morecore ():

  1. If the system also has no space to allocate, SBRK () returns-1. The CP is a char * type, and on some machines char unsigned, which requires a cast of type once.

  2. Thereturn value of the Morecore () call looks strange, don't worry, Freep will be modified in free (). The return value is also used in order to be compact in the malloc () of the judgment, p = Freep again-assigned statement.

Copy Code code as follows:

Free ()

void free (void *ap)
{
Header *bp,*p;
bp = (Header *) ap-1; /* point to block header * *
for (p=freep;! (bp>p && bp< p->s.ptr);p =p->s.ptr)
if (p>=p->s.ptr && (bp>p | | bp<p->s.ptr))
Break /* Freed block at start or end of arena*/
if (bp+bp->s.size==p->s.ptr) {/* Join to Upper NBR */
Bp->s.size + + p->s.ptr->s.size;
Bp->s.ptr = p->s.ptr->s.ptr;
} else
Bp->s.ptr = p->s.ptr;
if (p+p->s.size = = BP) {/* Join to Lower NBR */
P->s.size + + bp->s.size;
P->s.ptr = bp->s.ptr;
} else
P->s.ptr = BP;
Freep = p;
}


Free () First locates the relative position of the BP and the free list of the AP to be released, finds its nearest last and next free space, or finds the first and last elements of the free list when it is in front of or behind the entire free space. Note that because of the way malloc () is distributed and when free () is recycled (as mentioned below), you can guarantee that the entire free-space list will always rise from a low address, and point back to the first free space on the low address at the highest address.

After the positioning, according to the space to be released and adjacent to the neighboring space, to merge, or modify the corresponding space header. Two if side-by-side can enable BP to combine with high address and low address free space (if both are adjacent), or either or not merge.

After completing these three parts of the code (note that the same source file, sbrk () need #include <unistd.h>), you can use. Note, of course, that a function of the same name in the name and Stdlib.h is conflicting and can be renamed by itself.

The first time you look at the source, you will find that many implementations may not have thought: header structure and alignment fill, space rounding, linked list operation and initialization (boundary condition), malloc () call to Free (), malloc () and free () implicitly guaranteed list address order, etc. , it is really worth pondering. In addition to the two issues mentioned above, there are some simple thoughts on supplementary questions :

1.Header split with free space, header contains a pointer to its free space

This may not be necessary, and the corresponding algorithm needs to be changed. Also, because the header and free space are no longer contiguous, the space sbrk () should contain the header portion, and the memory distribution may be more trivial. Of course, this can also benefit from the use of other data structures to manage linked lists, such as hash by size, so that it is faster to find.

2. About SBRK ()

SBRK () is also a library function, it can make the heap to the stack direction of growth, specific reference: BRK (), SBRK () usage detailed.

3. The side that can be improved

The search for free space is linear, the lookup process can be thought of as a cyclic first-time adaptive algorithm in memory allocation, and may be slow in some cases, and if a data structure such as a hash table is indexed for different sizes of space, it is certainly possible to speed up the lookup itself and implement algorithms such as Best Bets. But the tradeoff is that it takes an extra time to modify this index, which is a trade-off.

The minimum allocation space in Morecore () is a macro definition, which can be passed as a parameter in actual use, and the minimum assigned lower bound is set as needed.

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.