동적 할당과 메모리 관리
1. 기억공간
C에서의 기억공간
- 프로그램의 실행을 위한 기억공간은 운영체제에서 할당
- 할당되는 기억공간의 영역 : 데이터 영역, 힙 영역, 스택 영역
1) 기억공간의 확보
① 메모리 정적할당(Static Allocation)
- 기억공간의 데이터 영역과 스택 영역 이용
- 프로그램을 작성하는 단계에서 필요한 기억공간의 크기를 결정
② 메모리 동적할당(Dynamic Allocation)
- 기억 공간의 힙 영역 이용
- 프로그램 실행중에 입력되는 자료에 맞게끔 기억공간의 크기를 결정
③ 기억공간의 할당영역
데이터 영역 : 전역변수와 static변수가 저장되는 영역 (정적 할당)
스택 영역 : 지역변수와 매개변수가 저장되는 영역 (정적 할당)
힙 영역 : 프로그래머의 필요에 의해 할당/소멸이 이루어지는 영역 (동적할당)
2) 메모리 정적할당과 동적할당
① 메모리 정적할당
- 변수 선언이나 배열 선언과 같이 프로그램을 작성하는 단계에서 필요한 기억 공간의 크기 결정
- 변수 선언과 같이 할당시켜줘야 할 기억공간의 크기를 명확히 알고 있을 경우, 프로그램이 시작
될때 미리 기억 공간의 크기를 고정하여 할당
② 메모리 정적할당의 장점과 단점
- 변수의 기억 공간의 크기가 명확할 때 기억공간을 쉽게 사용할수 있고, 에러발생확률 저하
- 사용하게 될 기억공간의 크기를 정확히 알지 못하거나 자료 각각의 크기 차이가 심하다면,
자료의 크기를 크게 잡아야 하므로 기억공간의 낭비를 가져옴
예) 메모리 정적할당의 문제점과 해결방법
3) 메모리 동적할당
① 메모리 동적할당의 장점과 단점
- 힙 영역을 이용하여 프로그램 실행 중에 입력되는 자료의 크기에 맞게 기억공간을 확보
많은 자료를 처리하는 배열의 크기를 실행 중에 정의해야 하는 경우에 특히 유용
(사용할만한 공간이 있어도 쪼개어져 있으면 사용불가)
- 프로그램 실행시 기억 공간의 크기를 지정이 가능하고, 재조정도 가능
- 함수를 이용하여 동적할당 및 메모리 회수를 위한 시간과 노력 소요
② 메모리 동적 할당순서
ⅰ) 기억공간을 동적으로 할당받을 변수를 포인터를 이용하여 선언
ⅱ) malloc()함수 등을 이용하여 기억공간을 동적으로 할당
ⅲ) 기억공간의 사용이 끝나면 free()함수를 이용하여 기억공간을 해제
③ 메모리 동적할당 함수
▣ malloc() 함수
- 할당받고자 하는 바이트를 설정하여 기억공간을 동적으로 할당
- 인자로 할당받고자 하는 기억 공간의 크기를 byte단위를 전달
힙 영역에 그 크기만큼 기억공간 할당, 할당한 기억공간의 첫번째 주소를 반환
- void로 명시하여 어떤 형으로든 변환 가능
- 초기화 안됨 (기억공간의 초기화를 위해서는 memset() 사용, *등을 이용하여 초기화가능)
- void * malloc(size_t number_of_bytes), 예) void malloc(sizeof(int));
▣ calloc()함수
- 할당받고자 하는 바이트 설정, 주어진 크기를 가지는 기억 공간을 할당받음
- malloc()함수와 동일하게 힙 영역에 기억공간 할당
- 사용하는 형태와 할당된 기억공간을 0으로 초기화
- void *calloc(int n, int size); ex) void *calloc(n, sizeof(int));
▣ realloc() 함수
- 이미 할당받은 기억 공간의 크기를 변경해야 할 필요가 있을 경우에 사용
int *a ;
a = (int *) calloc(5, sizeof(int)); ➡ int형 크기의 기억공간을 5개 할당
a = (int *) realloc(a, 10*sizeof(int)); ➡ int형 크기의 기억 공간을 10개 재할당
기존의 기억공간의 자료를 복사해옴
▣ free() 함수
- 동적으로 할당된 기억공간을 해제 (힙 영역의 할당된 공간은 프로그램 종료시까지 유지)
- 할당된 기억공간을 해제하지 않으면 기억공간의 부족 현상이 발생하므로 명시적 반납필요
- void free(void *p);
2. 기억공간 관리
- 기억공간 관리를 위한 함수 - memcmp, memcpy, memset 함수
- 관련 헤더 mem.h
① memcmp()함수
- 기억 공간에 들어있는 자료를 주어진 크기만큼 비교하여, 동일한지 여부를 알수 있게 해주는 함수
- 두개의 변수가 가리키는 기억 공간의 내용을 주어진 byte만큼 비교
- int memcmp(void *s1, void *s2, size_t n);
② memcpy()함수
- 기억 공간에 들어있는 자료를 다른 기억공간영역으로 복사하기 위한 함수
- 원래의 기억 공간에서 주어진 바이트만큼 새로운 기억 공간에 복사
- int memcpy(void *dest, void *src, size_t n); → src에서 dest로 복사
③ memset()함수
- 기억 공간에 들어있는 자료를 지정한 문자로 채우는 함수
- 할당된 기억 공간의 초기화나 내용 삭제를 위해 주로 사용
- 포인터가 가리키는 곳을 주어진 값으로 지정된 byte수만큼 채움
- void* memset(void* ptr, int value, size_t num) 예) memset(arr, 0, sizeof(int) * 5)
ptr : 메모리의 크기를 변경할 포인터, value : 초기화 값, size : 초기화 크기 반환 값