Search

동적할당

동적할당

정적 메모리 할당과 달리 상황에 따라 필요한 크기만큼의 메모리를 할당하는 것
⇒ heap 영역에 메모리 할당
포인터와 C언어 제공 라이브러리 함수를 활용한다

메모리할당 함수

<stdlib.h>에 정의되어 있는 malloc(), calloc(), realloc()
malloc() : 사용자가 원하는 크기만큼 메모리 할당
calloc() : 사용자가 원하는 크기만큼 메모리를 할당하고 0으로 초기화. 주로 배열/구조체 타입의 동적메모리 할당시 사용한다
realloc() : 기존에 저장되어 있던 데이터는 유지하고 메모리의 크기만 변경

메모리 해제 함수

free()
동적할당이라는 것 자체가 프로그래머가 상황에 맞춰 필요한 만큼의 메모리를 사용하겠다고 컴퓨터에게 요청해 빌리는 것이기 때문에 사용이 끝나면 반드시 반납해줘야 한다. == 메모리해제
int *arr; arr = (int *)malloc(sizeof(int)*5); if (arr==NULL) exit(1); free(arr); // free()의 파라미터에 메모리를 반환할 변수 넣어줌
C
복사
메모리 해제 작업 해주지 않으면 해당 메모리 영역은 컴퓨터가 필요할 때 사용할 수 없게 될 수도 있음 == 메모리 누수
메모리 누수 → 컴퓨터가 사용 가능한 메모리 감소 → 성능 저하
#include <stdio.h> #include <stdlib.h> int main() { int *pi = NULL; // NULL pointer : 포인터 변수를 초기화하기 위한 용도 pi = (int *)malloc(sizeof(int)*1); // pi에 4byte만큼의 메모리 할당 if (pi==NULL) exit(1); printf("%d", *pi); // 쓰레기값이 출력된다 free(pi); // 프로그램 종료 전 반드시 메모리 해제 return 0; }
C
복사
#include <stdio.h> #include <stdlib.h> int main() { int *pi = NULL; // NULL pointer : 포인터 변수를 초기화하기 위한 용도 pi = (int *)calloc(sizeof(int)*1); // pi에 4byte만큼의 메모리 할당 if (pi==NULL) exit(1); printf("%d", *pi); // 0이 출력된다 -> calloc함수는 메모리 할당과 동시에 0으로 초기화 free(pi); // 프로그램 종료 전 반드시 메모리 해제 return 0; }
C
복사
int *pi = NULL; // NULL pointer : 포인터 변수를 초기화하기 위한 용도 pi = (int *)malloc(sizeof(int)*1); // pi에 4byte만큼의 메모리 할당
: 앞에 (int *)는 리턴형이다. int형 포인터로 리턴한다는 의미이다.

함수별 1차원 배열 동적 할당

#include <stdio.h> #include <stdlib.h> int main() { int n = 5; int* arr1; arr1 = (int *)malloc(sizeof(int)*n); // n개의 int형 배열 할당 int n = 7; double* arr2; arr2 = (double *)calloc(n, sizeof(double)); // n개의 int형 배열 할당하고 0으로 초기화 arr2 = realloc(arr2, sizeof(double)*4); // 데이터는 유지하고 4개의 double형 배열 할당 return 0; }
C
복사
[calloc를 이용한 1차원 배열 동적할당]
#include <stdio.h> #include <stdlib.h> int main() { int n = 4; int* pi = NULL; // NULL pointer pi = (int*)calloc(n, sizeof(int)); // n개의 int형 배열을 할당하고 0으로 초기화 if (pi == NULL) exit(1); for (int i = 0; i < n; i++) printf("%d\n", pi[i]); free(pi); return 0; }
C
복사
[malloc를 이용한 1차원 배열 동적할당]
#include <stdio.h> #include <stdlib.h> int main() { int n = 4; int* pi = NULL; // NULL pointer pi = (int*)malloc(n, sizeof(int)); if (pi == NULL) exit(1); pi[0] = 1; pi[1] = 2; pi[2] = 3; for (int i = 0; i < n; i++) printf("%d\n", pi[i]); // 1, 2, 3이 순서대로 출력된 후 쓰레기값 출력되면서 오류남 free(pi); return 0; }
C
복사
[realloc를 이용한 1차원 배열 동적할당]
realloc은 할당 실패시 기존의 데이터도 잃을 수 있기 떄문에 주의가 필요합니다!
#include <stdio.h> #include <stdlib.h> int main() { int n = 4; int* pi = NULL; // NULL pointer pi = (int*)calloc(n, sizeof(int)); if (pi == NULL) exit(1); for (int i=0; i < n; i++) pi[i] = i; int m = 6; int* ptemp; ptemp = (int*)realloc(pi, sizeof(int) * m); // 파라미터로 포인터가 들어감 if (ptemp == NULL) exit(1); for (int i = 0; i < m; i++) printf("%d\n", ptemp[i]); free(pi); free(ptemp); return 0; }
C
복사
기존 pi에서 복사된 1, 2, 3
realloc 이후 추가된 배열 2개 출력
11p. Q. 왜 realloc이 후 추가된 값은 같은 값을 갖나요? 쓰레기값이라고 하셨는데 두 값이 같을 뿐 아니라 교수님 결과와 내 결과도 같음

2차원 배열의 동적 메모리 할당

이중포인터라이브러리 함수 사용
// ex. 5 x 10 행렬(int형 2차원 배열) int **p; p = (int**)malloc(sizeof(int*)*5); // 행을 만들어냄 if (p == NULL) exit(1); for (int i=0;i < 5; i++){ p[i] = (int*)malloc(sizeof(int)*10); // 열을 만들어냄 if (p[i] == NULL) exit(1); }
C
복사
2차원 배열의 동적할당 == 동적할당 2번
첫번째는 행, 두번째는 열을 생성
[malloc를 이용한 2차원 배열 동적할당]
#include <stdio.h> #include <stdlib.h> int main() { int n = 3, m = 5; // n x m의 2차원배열 생성할 것 double** p; p = (double**)malloc(n, sizeof(double)); if (p == NULL) exit(1); for (int i = 0; i < n; i++) { p[i] = (double*)malloc(sizeof(double) * m); // 1개의 행당 m개의 열 생성 if (p[i] == NULL) exit(1); } for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { printf("%d ", p[i][j]); } printf("\n"); } // 할당 해제 하는 부분 -> n + 1번 해제해주어야한다. for (int i = 0; i < n; i++) { free(p[i]); } free(p); return 0; }
C
복사
[해제가 수월하도록 하는 다른 방법 ( 강의 외 내용) ]
int height=8,width=6; int **arr; arr = (int **) malloc ( sizeof(int *) * height); arr[0] = (int *) malloc ( sizeof(int) * width*height ); for( int i=1; i<height; i++){ arr[i] = arr[ i-1 ] + width; } free(arr[0]); free(arr);
C
복사
그림으로 나타내면 다음과 같음
[calloc를 이용한 2차원 배열 동적할당]
#include <stdio.h> #include <stdlib.h> int main() { int n = 3, m = 5; // n x m의 2차원배열 생성할 것 double** p; p = (double**)calloc(n, sizeof(double)); if (p == NULL) exit(1); for (int i = 0; i < n; i++) { p[i] = (double*)calloc(m, sizeof(double)); // 1개의 행당 m개의 열 생성 if (p[i] == NULL) exit(1); } for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { printf("%d ", p[i][j]); } printf("\n"); } for (int i = 0; i < n; i++) { free(p[i]); }j free(p); return 0; }
C
복사
0으로 초기화된 모습