티스토리 뷰

728x90

☞ realloc, calloc

<stdlib.h>
void *realloc(void *ptr, size_t newsize);
void *calloc(size count, size_t eltsize);

realloc()은 동적 할당 메모리의 크기를 변경할 때 사용하고, calloc()은 항목 크기와 개수를 지정해서 배열 형태로 동적 메모리를 할당하고 메모리를 0으로 지운 상태로 리턴받을 때 사용 합니다. 두 내장 함수 모두 할당할 메모리가 없으면 NULL(0)을 리턴하므로 리턴 포인터가 정상적인지 확인해야 하고 리턴 타입이 void 포인터이므로 malloc()처럼 캐스팅해서 사용합니다.


realloc()은 ptr에 기존 메모리의 포인터를 전달하여 newsize에 해당하는 크기로 변경하는 작업을 수행하는데, 일반적으로 기존에 사용하던 메모리 블럭을 확장하는 것이 아니라 지정한 크기로 새로운 메모리를 할당하여 기존 메모리의 내용을 새로운 공간으로 복사하고 기존에 할당한 메모리를 해제한 다음 새로운 공간의 포인터를 리턴하는 방식으로 동작합니다. 최근 시스템에서는 기존 포인터 값을 NULL(0)로 전달하면 malloc() 처럼 동작하지만 예전 시스템에서는 시스템 오류를 발생시킬 수도 있으므로 호환성 확보를 위해서는 기존 포인터 값을 NULL로 전달하지 말아야 합니다. newsize로 전달한 값이 기존 메모리와 동일한 크기라면 변경없이 기존 포인터를 그대로 리턴합니다. 변경하는 새로운 메모리 크기는 기존보다 클 수도 작을 수도 있습니다.


calloc()는 메모리가 0으로 지워지는 것과 크기를 항목크기*항목개수로 전달하는 것을 제외하면 malloc()와 동일합니다.

☞ 예제1

......
    new_length = adj_array_p->cur_length + src_length - (end - start);
    if (new_length > adj_array_p->max_length)
    {
        void *new_buffer;
        int new_max = MAX (adj_array_p->min_length, MAX ((int) (adj_array_p->max_length * adj_array_p->rate), new_length));
        if (adj_array_p->buffer)
        {
            new_buffer = realloc (adj_array_p->buffer, new_max * adj_array_p->element_size);
        }
        else
        {
            new_buffer = malloc (new_max * adj_array_p->element_size);
        }

        if (!new_buffer)
        {
            return ADJ_ERR_BAD_ALLOC;
        }
        adj_array_p->buffer = new_buffer;
        adj_array_p->max_length = new_max;
    }
......

위의 코드는 큐브리드 DBMS 코드의 일부로 배열 크기를 재조정하는 구문에서 새로운 크기를 구한 다음에 기존에 포인터가 할당되어 있으면 realloc()으로 메모리를 재할당하고 포인터가 NULL이면 malloc()으로 처리하는 과정을 참조할 수 있습니다. 물론 메모리 할당 처리 이후에는 반드시 정상 여부를 확인하고 있습니다.


☞ 예제2

......
	LocalBufferDescriptors = (BufferDesc *) calloc(nbufs, sizeof(BufferDesc));
	LocalBufferBlockPointers = (Block *) calloc(nbufs, sizeof(Block));
	LocalRefCount = (int32 *) calloc(nbufs, sizeof(int32));
	if (!LocalBufferDescriptors || !LocalBufferBlockPointers || !LocalRefCount)
		ereport(FATAL,
				(errcode(ERRCODE_OUT_OF_MEMORY),
				 errmsg("out of memory")));
......

위의 코드는 PostgreSQL DBMS 코드의 일부로 내부 버퍼를 초기화하는 과정에서 calloc()함수를 적절하게 사용하는 과정을 살펴 볼 수 있습니다. 버퍼의 개수(nbufs)에 각 버퍼 항목별 타입의 크기를 sizeof()로 전달하여 nbufs * sizeof(...) 크기의 메모리를 할당하여 초기화하는 과정입니다. 이곳에서도 할당 받은 메모리의 정상 여부를 확인하고 있습니다.



728x90