Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h> //sbrk
- void *malloc(unsigned);
- void *calloc(unsigned, size_t);
- int main()
- {
- char a[] = "string to copy";
- char *b;
- int *arr;
- b = (char *)malloc(strlen(a) + 1);
- strcpy(b, a);
- printf("%s\n", b);
- arr = (int *)calloc(10, sizeof(int));
- for (int i = 0; i < 10; i++)
- printf("%d ", arr[i]);
- return 0;
- }
- typedef long Align; //для выравнивания по границе long
- union header { //заголовок блока
- struct
- {
- union header *ptr; //указатель на следующий свободный блок
- unsigned size; //размер этого блока
- } s;
- Align x; //принудительное выравнивание блока
- };
- typedef union header Header;
- static Header base; //пустой список для начального запуска
- static Header *freep = NULL; //начало в списке свободных блоков
- void *malloc(unsigned nbytes)
- {
- Header *p, *prevp;
- Header *morecore(unsigned);
- unsigned nunits;
- nunits = (nbytes + sizeof(Header) - 1) / sizeof(Header) + 1;
- if ((prevp = freep) == NULL)
- { //списка свободной памяти еще нет
- base.s.ptr = freep = prevp = &base; //структура с указателем на саму себя
- base.s.size = 0; //и нулевым размером
- }
- for (p = prevp->s.ptr;; prevp = p, p = p->s.ptr)
- {
- if (p->s.size >= nunits)
- { //достаточно большой блок
- if (p->s.size == nunits) //точно нужного размера
- 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) //прошли полнвй цикл по списку
- if ((p = morecore(nunits)) == NULL)
- return NULL; //больше памяти нет
- }
- }
- void *calloc(unsigned ncells, size_t cellsize)
- {
- Header *p, *prevp;
- Header *morecore(unsigned);
- unsigned nunits;
- nunits = (ncells * cellsize + sizeof(Header) - 1) / sizeof(Header) + 1; //malloc: (nbytes + sizeof(Header)-1)/sizeof(Header)+1
- if ((prevp = freep) == NULL)
- base.s.ptr = freep = prevp = &base;
- for (p = prevp->s.ptr;; prevp = p, p = p->s.ptr)
- {
- if (p->s.size >= nunits)
- {
- if (p->s.size == nunits)
- prevp->s.ptr = p->s.ptr;
- else
- {
- p->s.size -= nunits;
- p += p->s.size;
- p->s.size = nunits;
- }
- freep = prevp;
- /*заполнение блока памяти нулями*/
- for (char *q = (char *)(p + 1); ncells-- > 0; q += cellsize)
- *q = 0;
- return (void *)(p + 1);
- }
- if (p == freep)
- if ((p = morecore(nunits)) == NULL)
- return NULL;
- }
- }
- #define NALLOC 1024
- void free(void *);
- /*morecore запрашивает не более NALLOC единиц памяти*/
- Header *morecore(unsigned nu)
- {
- char *cp;
- Header *up;
- if (nu < NALLOC)
- nu = NALLOC;
- cp = (char *)sbrk(nu * sizeof(Header)); //(char *) – специально для Cxx
- if (cp == (char *)-1) //больше памяти нет
- return NULL;
- up = (Header *)cp;
- up->s.size = nu;
- free((void *)(up + 1));
- return freep;
- }
- void free(void *ap)
- {
- Header *bp, *p;
- bp = (Header *)ap - 1; //указатель на заголовок блока
- 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; //освобождаем блок в начале или в конце
- if (bp + bp->s.size == p->s.ptr)
- {
- 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)
- {
- p->s.size += bp->s.size;
- p->s.ptr = bp->s.ptr; //слить с нижним соседом
- }
- else
- p->s.ptr = bp;
- freep = p;
- }
Advertisement
Add Comment
Please, Sign In to add comment