Malloc 시뮬레이션
Malloc() 및 Free()
C 언어에서 배열은 고정된 수의 값 모음입니다. 배열의 크기가 선언되면 변경할 수 없습니다. 때로는 선언한 배열의 크기가 충분하지 않을 수 있습니다. 이 문제를 해결하기 위해 런타임 중에 수동으로 메모리를 할당할 수 있습니다. 이것은 C 프로그래밍에서 동적 메모리 할당으로 알려져 있습니다. 메모리를 동적으로 할당하기 위해 라이브러리 함수인 malloc(), calloc(), realloc() 및 free()가 사용됩니다. 이러한 기능은 헤더 파일에 정의되어 있습니다.
맬록()
"malloc"이라는 이름은 메모리 할당을 나타냅니다. malloc() 함수는 지정된 바이트 수의 메모리 블록을 예약합니다. 그리고 모든 형식의 포인터로 변환할 수 있는 void 포인터를 반환합니다.
malloc() 구문
ptr = (castType*) malloc(크기);
예:- ptr = (float*) malloc(100 * sizeof(float));
위의 명령문은 400바이트의 메모리를 할당합니다. float의 크기가 4바이트이기 때문입니다. 그리고 포인터 ptr은 할당된 메모리의 첫 번째 바이트의 주소를 보유합니다.
메모리를 할당할 수 없는 경우 표현식 결과는 NULL 포인터입니다.
무료()
C의 다른 언어와 마찬가지로 malloc()으로 생성된 동적으로 할당된 메모리는 자체적으로 해제되지 않습니다. 개발자는 명시적으로 free()를 사용하여 이전에 할당한 공간을 해제해야 합니다.
free() 구문
무료(ptr);
이 "Malloc 및 Free" 시뮬레이션에서,
메모리로 간주되는 25000바이트 길이의 배열과 모든 할당은 해당 메모리를 사용하여 수행됩니다. malloc()의 시뮬레이션 버전을 MyMalloc()이라고 하고 free()의 시뮬레이션 버전을 MyFree()라고 합니다.
실제 malloc()과 마찬가지로 첫 번째 MyMalloc() 함수는 크기를 매개변수로 요구하고 그 다음 함수는 25000바이트 풀에서 그만큼의 메모리를 할당합니다(주어진 메모리 크기에 가장 적합한 메모리 위치를 찾아 할당합니다. ). 마지막으로 함수는 포인터를 반환합니다.
할당이 발생하면 메모리 풀의 25000바이트가 다양한 크기의 메모리 블록으로 나뉩니다. 이러한 메모리 블록을 연결하기 위해 모든 메모리 블록을 연결 목록에 넣습니다. 모든 메모리 블록은 헤드 및 테일 블록을 제외한 두 개의 다른 블록에 연결됩니다. 이러한 메모리 블록에 대한 정보를 추적하기 위해 메타 데이터가 사용됩니다. 모든 메모리 블록에는 메타 데이터 섹션이 있습니다. 메타 데이터는 해당 블록이 할당되었는지 여부, 블록 크기 및 다음 블록의 포인터를 추적합니다.
MyFree()는 또한 할당된 메모리의 포인터를 매개변수로 필요로 하며 실제 free()와 똑같이 작동합니다.
함수는 할당된 메모리 블록의 메타데이터를 변경하여 할당된 블록을 사용 가능한 것으로 설정합니다. 그런 다음 다음 또는/및 이전 블록이 사용 가능한지 확인하고 사용 가능한 경우 해당 블록은 새로 사용 가능한 블록과 병합되어 새 블록을 생성합니다.
파일
#include <stdio.h>
#include<stddef.h>
#include "mymalloc.h"
struct metaData *metaList = NULL;
/* This is for malloc first use, just initialize the first node of metaData linked list*/
struct metaData *initializeMemory(void *startPtr, size_t sizeMem)
{
struct metaData *tmp = (struct metaData *)startPtr;
tmp->STATUS = FREE;
tmp->NEXT = NULL;
tmp->SIZE = sizeMem - sizeof(struct metaData);
return tmp;
}
/* Create a new node and add it before node which point "nextptr" */
struct metaData *newMeta(struct metaData *startPtr, size_t sizeMem, struct metaData *nextPtr)
{
struct metaData *tmp = startPtr;
tmp->STATUS = FREE;
tmp->NEXT = nextPtr;
tmp->SIZE = sizeMem - sizeof(struct metaData);
return tmp;
}
/*Find the best fited node in the linkedlist and returns it's pointer*/
struct metaData *searchBestFit(size_t targetSize)
{
struct metaData *tmp = metaList;
struct metaData *min = NULL;
while (tmp)
{
if (min == NULL && (tmp->SIZE) >= targetSize && (tmp->STATUS) == FREE)
min = tmp;
else if (min && (tmp->SIZE) >= targetSize && (tmp->SIZE) < (min->SIZE) && (tmp->STATUS) == FREE)
{
min = tmp;
}
tmp = tmp->NEXT;
}
return min;
}
/* Just for testing purposes, print all nodes in the linked list*/
void printMemory(struct metaData *ptr)
{
//if metaList is empty,create a new node and init all memory to it
if (!metaList)
{
metaList = initializeMemory((void *)MEMORY, MEMSIZE);
ptr=metaList;
}
while (ptr)
{
printf("[PTR=%p]\t[STARTPTR=%p]\t[SIZE=%ld]\t[STATUS=%s]\t[NEXTPTR=%p]\t\n", ptr, ptr + 1, ptr->SIZE, (ptr->STATUS == 0) ? "ALLOC" : "FREE", ptr->NEXT);
ptr = ptr->NEXT;
}
printf("\n\n");
return;
}
void *MyMalloc(size_t givenSize)
{
//if metaList is empty,create a new node and init all memory to it
if (!metaList)
{
metaList = initializeMemory((void *)MEMORY, MEMSIZE);
}
struct metaData *ptr;
ptr = searchBestFit(givenSize + sizeof(struct metaData));
//if there is a fitted slot for the given node setup it for use otherwise return NULL
if (ptr)
{
char *tmp;
tmp = (char *)ptr;
tmp = tmp + (int)sizeof(struct metaData) + (int)givenSize;
ptr->NEXT = newMeta((struct metaData *)tmp, ptr->SIZE - givenSize, ptr->NEXT);
ptr->SIZE = givenSize;
ptr->STATUS = ALLOCATED;
return ptr + 1;
}
else
{
fprintf(stderr, "Error ! Out Of Memory \n\n");
return NULL;
}
}
/* Sreach for a node,which it's nextnode has "locAddress" and return it*/
struct metaData *preMeta(void *locAddress)
{
struct metaData *tmp = metaList;
struct metaData *preTmp = metaList;
while (tmp)
{
if (tmp + 1 == locAddress)
{
return preTmp;
}
preTmp = tmp;
tmp = tmp->NEXT;
}
return NULL;
}
void MyFree(void *givenAddress)
{
//if the first node has that "givenAddress" just free it
if (givenAddress == metaList + 1)
{
metaList->STATUS = FREE;
if (metaList->NEXT != NULL)
{
//if second node is also a free node mearge them together
if (metaList->NEXT->STATUS == FREE)
{
struct metaData *tmp;
tmp = metaList;
size_t newSize = tmp->SIZE + tmp->NEXT->SIZE + sizeof(struct metaData);
tmp->SIZE = newSize;
tmp->NEXT = tmp->NEXT->NEXT;
}
}
}
else
{
struct metaData *preMetaAddress = preMeta(givenAddress);
//if there is a pointer called "givenAddress" make it free and mareage with near free slots
if (preMetaAddress)
{
preMetaAddress->NEXT->STATUS = FREE;
//if node is last one
if (preMetaAddress->NEXT->NEXT == NULL)
{
if (preMetaAddress->STATUS == FREE)
{
preMetaAddress->SIZE = preMetaAddress->SIZE + preMetaAddress->NEXT->SIZE + sizeof(struct metaData);
preMetaAddress->NEXT = preMetaAddress->NEXT->NEXT;
}
}
else
{
// prevNode and nextNode both are empty
if (preMetaAddress->STATUS == FREE && preMetaAddress->NEXT->NEXT->STATUS == FREE)
{
preMetaAddress->SIZE = preMetaAddress->SIZE + preMetaAddress->NEXT->SIZE + preMetaAddress->NEXT->NEXT->SIZE + sizeof(struct metaData) * 2;
preMetaAddress->NEXT = preMetaAddress->NEXT->NEXT->NEXT;
}
//only prevNode is empty
else if (preMetaAddress->STATUS == FREE)
{
preMetaAddress->SIZE = preMetaAddress->SIZE + preMetaAddress->NEXT->SIZE + sizeof(struct metaData);
preMetaAddress->NEXT = preMetaAddress->NEXT->NEXT;
}
//only nextNode is empty
else if (preMetaAddress->NEXT->NEXT->STATUS == FREE)
{
preMetaAddress->NEXT->SIZE = preMetaAddress->NEXT->SIZE + preMetaAddress->NEXT->NEXT->SIZE + sizeof(struct metaData);
preMetaAddress->NEXT->NEXT = preMetaAddress->NEXT->NEXT->NEXT;
}
}
}
else
{
fprintf(stderr, "Error ! Enter a Valid Pointer");
}
}
return;
}
/***** MYMALLOC FUNCTION USING BEST FIT ******/
#include<stddef.h>
#include<stdio.h>
#define FREE 1
#define ALLOCATED 0
#define MEMSIZE 25000
char MEMORY[MEMSIZE];//create byte addressed array
struct metaData{
int STATUS;
size_t SIZE;
struct metaData * NEXT;
};
struct metaData * initializeMemory(void *startPtr, size_t sizeMem);
struct metaData * newMeta(struct metaData *startPtr, size_t sizeMem, struct metaData *nextPtr);
struct metaData * searchBestFit(size_t targetSize);
void printMemory(struct metaData *ptr);
void * MyMalloc(size_t givenSize);
struct metaData * preMeta(void *locAddress);
void MyFree(void *givenAddress);
`
testCases.c - 샘플 테스트 사례
`
#include<stdio.h>
#include "mymalloc.c"
int main()
{
printMemory(metaList);
char * x=MyMalloc(10000);
printMemory(metaList);
char * y=MyMalloc(1000);
printMemory(metaList);
MyFree(y);
printMemory(metaList);
char * z=MyMalloc(27000);
printMemory(metaList);
return 0;
}
`
참고: 메모리 조각 모음 절차는 구현되지 않습니다.
보기GitHub
이슈와 PR은 환영합니다 🙂
Reference
이 문제에 관하여(Malloc 시뮬레이션), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/rdperera/malloc-simulation-1gal텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)