[C] std library - malloc, calloc, realloc 에 대한 몇가지

숲사람·2022년 5월 3일
0
post-custom-banner

기본 사용법

  • malloc(할당할 갯수 * 자료구조 크기)
  • calloc(할당할 갯수, 자료구조 크기)
  • realloc(포인터, 변경할 사이즈)

realloc 으로 C++ 의 vector구현하기.

realloc으로 다이나믹하게 array 사이즈를 변경시키는 Dynamic Array구현 가능.
vector의 push_back() 구현. 약간 OOP스럽게 구현해봤다. 앞으로 유용하게 쓸듯!

#include <stdio.h>
#include <stdlib.h>

struct elem {
        int val;
};

struct vector {
        int v_size;
        int v_last;
        struct elem *arr;
        void (*push_back)(struct vector *, int);
};

void cb_push_back(struct vector *this, int val)
{
        if (this->v_last >= this->v_size) {
                this->v_size *= 2; // increase by double size
                this->arr = (struct elem *)realloc(this->arr, sizeof(struct elem) * this->v_size);
                printf("resize vector by %d (val:%d)\n", this->v_size, val);
        }
        this->arr[this->v_last++].val = val;
}

struct vector *vector_init(int size)
{
        struct vector *v = (struct vector *)calloc(1, sizeof(struct vector));
        v->push_back = cb_push_back; // assign call back function
        v->v_last = 0; // last idx
        v->v_size = size; 
        v->arr = (struct elem *)calloc(v->v_size, sizeof(struct elem));
        return v;
}

int main(int argc, char *argv[])
{
        struct vector *myvt = vector_init(1);

        myvt->push_back(myvt, 10);
        myvt->push_back(myvt, 20);
        myvt->push_back(myvt, 30);
        myvt->push_back(myvt, 40);
        myvt->push_back(myvt, 50);
        myvt->push_back(myvt, 60);
        myvt->push_back(myvt, 70);
        myvt->push_back(myvt, 80);
        myvt->push_back(myvt, 90);
        myvt->push_back(myvt, 100);

        for (int i = 0; i < myvt->v_last; i++)
                printf("(%d)", myvt->arr[i].val);
        printf("\n");

        return 0;
}

실행 결과

$ ./ra 
resize vector by 2 (val:20)
resize vector by 4 (val:30)
resize vector by 8 (val:50)
resize vector by 16 (val:90)
(10)(20)(30)(40)(50)(60)(70)(80)(90)(100)

malloc() + memset() vs calloc() 성능 비교

로컬에서 돌려보니 놀랍게도 calloc이 malloc + memset조합보다 월등히 빠르다. (적어도 아래 코드를 로컬에서 실행했을때). 아래 답변에 따르면 보통 비슷한데 calloc은 보다 일을 적게할수 있기때문이다. memset()하는 부분을 skip할 수도 있기 때문. 그런데 malloc() + memset() 은 모두 fully하게 실행된다. 자세한 내용은 아래 출처 참고.
출처: https://stackoverflow.com/questions/2688466/why-mallocmemset-is-slower-than-calloc

$ time ./ma 
real    0m4.446s
user    0m1.191s
sys     0m3.253s

$ time ./ca
real    0m0.100s
user    0m0.039s
sys     0m0.048s
  • malloc.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define BLOCK_SIZE 1024*1024*256
#define BUF_SIZE 50

int main()
{
        int i=0;
        char *buf[BUF_SIZE];

        while(i < BUF_SIZE) {
                buf[i] = (char*)malloc(BLOCK_SIZE);
                memset(buf[i], 0, BLOCK_SIZE);
                i++;
        }
}
  • calloc.c
#include<stdio.h>
#include<stdlib.h>
#define BLOCK_SIZE 1024*1024*256
#define BUF_SIZE 50

int main()
{
        int i=0;
        char *buf[BUF_SIZE];

        while(i < BUF_SIZE) {
                buf[i] = (char*)calloc(1, BLOCK_SIZE);
                i++;
        }
}
  • Makefile
all: ca ma

calloc.o: calloc.c
        gcc -c calloc.c -o calloc.o

malloc.o: malloc.c
        gcc -c malloc.c -o malloc.o
        
ca: calloc.o 
        gcc calloc.o -o ca
    
ma: malloc.o    
        gcc malloc.o -o ma

clean:  
        rm -rf *.o
        rm ca ma
profile
기록 & 정리 아카이브용
post-custom-banner

0개의 댓글