메모리 동적 할당
메모리 정/동적 할당의 개념과 동적할당함수의 기능과 사용법, 메모리 관리 함수.
- 학습 목표
- 메모리 정적할당과 동적할당의 이해.
- 메모리 동적할당함수를 이용하여 프로그램 작성.
- 메모리 관리함수의 기능 이해.
주요 용어
- 데이터 영역 : 전역변수와 static 변수가 저장되는 기억공간 영역.
- 힙(heap) 영역 : 프로그래머의 필요에 의해 할당과 소멸이 이루어지는 기억공간 영역.
- 스택(stack) 영역 : 지역변수와 매개변수가 저장되는 기억공간 영역.
- 메모리 정적할당 : 프로그램이 작성되는 단계에서 기억공간의 크기가 결정되는 기억공간 확보방법.
- 메모리 동적할당 : 프로그램이 실행되는 중에 입력되는 자료에 따라 기억공간의 크기를 결정할 수 있는 기억공간 확보방법.
메모리 동적할당의 개념
C 언어에서의 기억공간?
- 프로그램의 실행을 위해 기억공간 필요.
- 기억공간은 운영체제에서 할당.
- 할당되는 기억공간의 영역.
- 데이터 영역.
- 전역변수와 static 변수가 저장되는 영역.
- 프로그램이 시작하면서 할당되고, 종료하면 소멸하게 됨.
- 힙 영역
- 개발자의 필요에 의해 할당/소멸이 이루어지는 영역.
- 프로그램이 실행되는 중에 크기가 변함.
- 메모리 동적 할당에 사용되는 영역.
- 스택 영역
- 지역변수와 매개변수가 저장되는 영역.
- 함수 호출이 완료되면 사라짐.
- 데이터 영역.
기억공간의 확보
메모리 정적 할당(Static Allocation)
- 기억공간의 데이터 영역과 스택 영역 이용.
- 프로그램을 작성하는 단계에서 필요한 기억공간의 크기를 결정.
메모리 동적 할장(Dynamic Allocation)
- 기억공간의 힙 영역 이용.
- 프로그램 실행 중에 입력되는 자료에 맞게끔 기억공간의 크기를 결정.
메모리 정적할당
- 변수 선언이나 배열 선언과 같이 프로그램을
작성하는 단계에서 필요한 기억 공간의 크기를 결정.
- 변수 선언과 같이 할당 시켜줘야 할 기억공간의 한계 크기를 명확히 알고 있을 경우 사용.
- 메모리 정적 할당은 프로그램이 시작될 때 미리 기억공간의 크기를 고정하여 할당.
메모리 정적할당의 예
#include <stdio.h> void test1(int); void test2(int); // 전역변수로 선언되어 데이터 영역에 할당. // 프로그램 종료될 때까지 존재. int a = 100; void main() { // 지역변수로 스택 영역에 할당. // main()가 종료될 때까지 존재. int b = a; test1(b); test2(b); } // test1이 호출되면, // 매개변수 c와 지역변수 d는 스택영역에 할당. // test1이 종료되면 c, d는 지워짐. void test1(int c) { int d; d = c + 10; printf("%d\n", d); } // test2가 호출되면, // 매개변수 e와 지역변수 f는 스택영역에 할당. // 종료되면 d, f는 지워짐. void test2(int e) { int f; f = e + 20; printf("%d\n", f); } // main()가 종료되면 스택영역에 할당된 b도 제거. // 프로그램이 끝아면 a도 제거.메모리 정적할당의 장/단점
- 장점
- 프로그램에서 사용하게 될 변수의 기억 공간의 크기를 명확히 알고 있다면,
메모리 정정할당은 쉽게 기억 공간을 사용할 수 있고, 에러의 발생 확률을 줄일 수 있음.
- 프로그램에서 사용하게 될 변수의 기억 공간의 크기를 명확히 알고 있다면,
- 단점
- 사용하게 될 기억 공간의 크기를 정확히 알지 못하거나, 사용되는 자료의 크기가 각각 차이가 심하다면,
기억공간의 낭비를 가져오게 됨.
- 사용하게 될 기억 공간의 크기를 정확히 알지 못하거나, 사용되는 자료의 크기가 각각 차이가 심하다면,
메모리 정적할당의 문제점
#include <stdio.h> void main() { int size; // 배열의 크기를 변수로 선언하면 에러 발생? char a[size]; printf("입력할 문자열의 크기? : "); scanf("%d", &size); printf("주소 : "); scanf("%s", a); printf("입력된 주소 %s\n", a); } #include <stdio.h> #include <stdlib.h> void main() { int size; char *a; printf("입력할 문자열의 크기? : "); scanf("%d", &size); // 메모리 동적할당. a = (char *)malloc(sizeof(char) * size); printf("주소 : "); scanf("%s", a); printf("입력된 주소 %s\n", a); free(a); }메모리 동적할당 함수
malloc(), calloc(), realloc(), free() 등
메모리 동적할당의 장/단점
- 힙 영역을 이용하여 프로그램 실행 중에 입력되는 자료의 크기에 맞게 기억 공간 확보.
- 많은 자료를 처리하는 배열의 크기를 실행 시간에 정의해야 하는 경우에 유용.
- 프로그램 실행 시 기억 공간의 크기를 지정/재조정 가능.
- 시간이 지체되는 단점.
메모리 동적할당 순서
- 기억공간을 동적으로 할당 받을 변수를 포인터를 이용하여 선언.
- malloc() 등을 이용하여 기억공간을 동적으로 할당 가능.
- 기억공간의 사용이 끝나면 free()를 이용하여 기억공간 해제.
malloc()
- 인자로 할당 받고자 하는 기억 공간의 크기를 byte 단위로 전달.
- 힙 영역에 그 크기만큼 기억 공간을 할당, 할당한 기억공간의 첫 번째 주소 반환.
- void*로 명시하여 어떤 형이든 형 변환 가능.
- 초기화 안됨(기억공간의 초기화를 위해서는 memset() 사용).
- 형식 : void * malloc(size_t, number_of_bytes);
- 기능 : number_of_bytes에서 주어지는 크기만큼 기억 공간을 동적으로 할당.
- 예 : void * malloc(sizeof(int));
free()
- 메모리
해제 함수.
- 힙 영역에 할당된 공간은 프로그램이 종료될 때까지 유지됨.
- 할당된 기억 공간을 해제하지 않으면, 공간 부족 현상 발생.
- 명시적인 반남.
- 형식 : void free(void *p);
- 기능 : 동적으로 할당된 기억 공간을 해제할 때 사용.
메모리 동적할당 예 - 1
#include <stdio.h> #include <stdlib.h> void main() { // 1) 동적할당을 위한 포인터변수 선언. int *a; // 2) 기억공간 할당, // - (int *)는 왼쪽의 포인터변수 a와 자료형을 일치시키기 위한 // 강제 형변환. a = (int *)malloc(sizeof(int)); if (a == NULL) { puts("FAILLURE OF ALLOCATION!"); exit(1); } *a = 20; printf("VARIABLE a : %d\n", *a); // 3) 할당받은 기억공간 해제. free(a); }메모리 동적할당 예 - 2
#include <stdio.h> #include <stdlib.h> #pragma warning(disable : 4996) void main() { // 입력받을 문자 수 저장 변수 선언. int size; // 1) 동적 할당된 기억공간을 연결할 포인터. char *str; printf("INSERT SIZE OF STRING : "); scanf("%d", &size); // 2) 입력 받을 문자 수(size + 1)에 맞게 동적 할당. str = (char *)malloc(size + 1); if (str == NULL) { puts("FAILLURE OF ALLOCATION!"); exit(1); } printf("INSERT STRING : "); // 동적으로 할당된 기억공간에 문자열 저장. scanf("%s", str); printf("STRING THAT SAVED AT DYNAMIC MEMORY : \n%s\n", str); // 3) 할당받은 기억공간 해제. free(str); }calloc()
- malloc()와 동일하게 힙 영역에 기억공간 할당.
- 사용하는 형태와 할당된 기억 공간을 0으로 초기화.
- 형식 : void * calloc( int n, int size );
- 기능 : 주어진 size의 크기를 갖는 기억 공간 n개를 할당.
- 예 : void * calloc( n, sizeof(int));
realloc()
- 이미 할당 받은 기억 공간의 크기를 변경해야 할 필요가 있을 때 사용.
- 형식 : void * realloc( void *p, int size);
- 기능 : 포인터 p가 가리키고 있는 기억공간의 크기를 지정된 size의 크기로 변경.
기억공간 관리함수
memcmp(), memcpy(), memset()
memcmp()
- 기억 공간에 들어 있는 자료를 주어지는 크기만큼 비교하여, 같은지 여부를 알 수 있게 해주는 함수.
- 형식 : int memcmp( void *s1, void *s2, size_t n);
- 기능 : s1, s2가 가리키고 있는 기억 공간의 내용을 n byte 만큼 비교.
- n바이트만큼 비교하여 s1 > s2 면 양수, s1 < s2 면 음수, s1 == s2 면 0 반환.
memcpy()
- 기억 공간의 자료를 다른 기억 공간 영역으로 복사하기 위한 함수.
- 형식 : void * memcpy( void *dest, const void * src, size_t n);
- 기능 : src에서 n byte만큼 dest에 복사.
memset()
- 기억 공간의 자료를 지정한 문자로 채우는 함수.
- 할당된 기억 공간의 초기화나 내용 삭제를 위해 주로 사용.
- 형식 : void * memset( void *s, int c, size_t n );
- 기능 : 포인터 s가 가리키는 곳을 c 값으로 n byte 만큼 채운다.