벌써 알고리즘 3주차가 끝났다. 이제부터 C언어 시작,, 화이팅!!! 문과출신 비전공자라서 내가 접한 C언어는 정처기 공부할 때 공부한게 다지만 무튼 정글하면서 열심히 독파해보자
!
컴파일 타임이 아닌 프로그램이 실행되는 중인 런타임에 필요한 만큼의 메모리 공간을 확보하는 것
컴퓨터 프로그래밍에서 실행(런타임)에 사용할 메모리 공간을 할당하는 것
-> 그때 그떄 필요한 메모리 공간 확보, 이를 다 사용했으면 free
시켜 줌으로써 메모리 공간 해제 -> 메모리 공간을 효율적으로 사용.
주로 필요한 메모리의 크기가 실행시간에 결정. 메모리의 요구사항이 변할 수 있는 경우 유용 -> 메모리 할다 ㅇ이후에는 꼭 메모리 해제하여 메모리 누수(memory leak)
을 방지해야 함
메모리 누수:
동적으로 할당된 메모리를 해제하지 않아 시스템의 메모리가 점차 고갈되는 상황
스택(Stack)
: 함수가 종료되거나 변수의 영역을 벗어나면 자동으로 메모리 해제
힙(Heap)
: 원시 자료형이 아닌 보다 큰 크기의 데이터를 담고자 동적으로 할당하는 메모리 공간
동적 할당(dynamic allocation)
: 힙 영역
에 필요한 만큼의 메모리 공간 할당 -> 더 이상 필요하지 않으면 메모리 해제
malloc
, calloc
), 이미 할당된 메모리라도 언제든지 크기 조정 가능(realloc
)free
)해야함 (메모리 누수
방지를 위해) int *a = malloc(5); //5 byte 메모리 공간 선언
int *b = malloc(10); //10 byte 메모리 공간 선언
b= a; // b는 a의 주소를 가리키는 상황
free(a); //a 메모리 할당 해제
free(b);
free(b)
: 이미 해제된 메모리 주소를 다시 해제하련느 시도 -> 잘못된 메모리의 해제, 메모리 누수. b가 원래 가리키던 10바이트의 메모리는 해제되지 않은 채로 남아있게 됨. => 프로그램이 종료될 때까지 사용할 수 없는 상태로 남아있게 된다.
#include <stdio.h>
#include <stdlib.h>
int main() {
// int 자료형 크기에 해당하는 메모리를 heap영역에 동적으로 할당
// 할당된 메모리의 주소를 data 포인터에 저장
int *data = (int *)malloc(sizeof(int));
// 메모리 할당이 실패하면 malloc 은 NULL 포인터 반환
// NULL인지 확인하여 메모리 할당이 성공적으로 이루어졌는지 검사
if (data == NULL){
perror("Memory allocation failed");
return ;
}
//메모리 할당에 성공한 경우 프로그램 종료되기 전에 free 함수 선언하여
//할당된 메모리 해제
// free: data가 가리키는 메모리 해제 - 해당 메모리 블록을 힙 영역에 반환
free(data);
return 0;
}
malloc(memory allocation)
단순히 요청한 크기 만큼의 메모리 블록 할당. 할당된 메모리의 시작 주소 반환. 메모리 할당에 실패하면 NULL 반환
#include <stdio.h> #include <stdlib.h> int main() { int *ptr; int형 변수 5개 크기만큼의 메모리 할당 ptr = (int*)malloc(5 * sizeof(int)); if (ptr ==NULL) { printf("메모리 할당 실패\n"); return 1; } // 작업 수행 free(ptr); return 0; }
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int arr[4] = {4, 3, 2, 1}; // 크기가 4인 배열
int * pArr; // int 타입을 가리키는 포인터 pArr
//int 타입 사이즈 * 4 만큼의 메모리 할당
pArr = (int *)malloc(sizeof(int) * 4);
//메모리 할당 실패시
if (pArr == NULL) {
printf("malloc error")
}
for (int i = 0; i <4; ++i) {
pArr[i] = arr[i];
}
for (int i=0; i <4; ++i) {
printf("%d \n", pArr[i]);
}
//할당한 메모리 해제
free(pArr);
system("pause");
return 0;
}
sizeof(int) * 4
: 배열의 크기가 4라서 동일한 타입인 int * 4사이즈로 메모리 할당
calloc(contiguous allocation)
할당된 메모리를 0으로 초기화
요소 수(num_elements)와 요소 크기(element_size)를 입력받아 메모리 할당
-> 할당된 메모리는 모두 비트가 0으로 초기화된다.
메모리 할당에 실패하면 NULL을 반환한다.#include <stdio.h> #include <stdlib.h> int main() { int len = 4; int *arr = (int *)calloc(len, sizeof(int)); for (int i=0; i<len; i++){ printf("%d", arr[i]); } }
출력 결과는 전부 0으로 초기화했으니0000
이 나온다.
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr;
int num_elements = 5;
//int 형 변수 5개 크기 만큼의 메모리를 0으로 초기화하여 할당
ptr = (int *)calloc(num_elements, sizeof(int));
if (ptr == NULL) {
printf("메모리 할당 실패\n");
return 1 ;
}
//메모리 할당 후 필요한 작업 수행
//할당된 메모리 해제
free(ptr);
return 0;
}
realloc(Re-allocation)
이미 할당된 메모리 블록의 크기를 변경하거나 새로운 크기로 재할당. ptr이 가리키는 메모리 블록을 new_size에 맞게 조정하고 이전 데이터를 새로운 크기에 맞게 유지하거나 복사
메모리 재할당에 실패하면NULL
반환하고 원래 메모리는 변경되지 않음
#include <stdio.h>
#include <stdlib.h>
int main() {
int len = 4;
int len2 = 10;
int *arr = (int *)malloc(sizeof(int)*len);
if (arr==NULL) {
printf("메모리 할당 실패\n");
return 1;
}
for (int i= 0; i< len; i++){
arr[i] = i;
}
arr = (int *)realloc(arr, sizeof(int)*len2);
if (arr== NULL){
printf("메모리 재할당 실패\n");
return 1 ;
}
for (int i= len; i<len2; i++) {
arr[i] = i;
}
printf("배열 요소 출력: ");
for (int i =0; i<len2; i++) {
printf("%d", arr[i]);
}
free(arr);
return 0 ;
}
free(free memory)
malloc
,calloc
,realloc
을 통해 할당된 메모리 해제
-> 메모리 블록 해제하고 해당 메모리는 다시 사용 가능한 상태가 된다 .
예시 코드
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int num; //총 과목 수
int *pArr; //점수를 저장할 배열을 가리킬 포인터
int average = 0; // 평균 점수
// 저장할 과목수 num 입력 받기
printf("몇개의 과목을 저장할 것인가요?");
scanf("%d", &num);
// 입력 받은 수가 0
if (num ==0) {
return 0;
}
//과목 수에 해당하는 크기의 정수 배열을 동적 할당
pArr = (int*)malloc(sizeof(int)*num);
//메모리 할당 실패시 오류 메시지 출력
if (pArr== NULL) {
printf("malloc error");
exit(1);
}
//각 과목 점수 입력 받기
for (int i =0; i<num; ++i){
printf("[%d/%d] 점수 입력 : ", i + 1 ,num);
scanf("%d", &pArr[i]);
}
// 입력받은 각 과목 점수 출력
for (int i=0; i<num; ++i) {
printf("%d번쨰 과목의 점수: %d\n", i +1, pArr[i]);
}
//입력받은 점수들의 평균 계산
for (int i = 0; i <num; ++i) {
average += pArr[i];
}
average /= num;
printf("평균: %d\n", average);
//동적으로 할당받은 배열 메모리 해제
free(pArr);
system("pause");
return 0;
}
(int*)malloc(sizeof(int) * num)
을 사용하여 num개의 정수를 저장할 배열을 동적 할당
메모리를 할당하고 해제하는 malloc과 free함수는
stdlib.h
헤더파일 내에 정의되어 있다.
참고)
https://jeckl.tistory.com/entry/C%EC%96%B8%EC%96%B4-23%EA%B0%95-%EB%A9%94%EB%AA%A8%EB%A6%AC%EC%9D%98-%EB%8F%99%EC%A0%81%ED%95%A0%EB%8B%B9-malloc-calloc-realloc-free
https://dsnight.tistory.com/50
https://blockdmask.tistory.com/290
https://velog.io/@saint6839/C%EC%96%B8%EC%96%B4-%EB%8F%99%EC%A0%81-%EB%A9%94%EB%AA%A8%EB%A6%AC-%ED%95%A0%EB%8B%B9-%EA%B0%9C%EB%85%90-%EC%9E%A1%EA%B8%B0