[Jungle] Week4. malloc, calloc, realloc 함수

somi·2024년 4월 12일
0

[Krafton Jungle]

목록 보기
21/68

C언어

벌써 알고리즘 3주차가 끝났다. 이제부터 C언어 시작,, 화이팅!!! 문과출신 비전공자라서 내가 접한 C언어는 정처기 공부할 때 공부한게 다지만 무튼 정글하면서 열심히 독파해보자
!


정적 메모리 할당(Static allocation)

컴파일 타임이 아닌 프로그램이 실행되는 중인 런타임에 필요한 만큼의 메모리 공간을 확보하는 것

동적 메모리 할당(Dynamic allocation)

컴퓨터 프로그래밍에서 실행(런타임)에 사용할 메모리 공간을 할당하는 것
-> 그때 그떄 필요한 메모리 공간 확보, 이를 다 사용했으면 free시켜 줌으로써 메모리 공간 해제 -> 메모리 공간을 효율적으로 사용.
주로 필요한 메모리의 크기가 실행시간에 결정. 메모리의 요구사항이 변할 수 있는 경우 유용 -> 메모리 할다 ㅇ이후에는 꼭 메모리 해제하여 메모리 누수(memory leak)을 방지해야 함

메모리 누수:
동적으로 할당된 메모리를 해제하지 않아 시스템의 메모리가 점차 고갈되는 상황


스택(Stack): 함수가 종료되거나 변수의 영역을 벗어나면 자동으로 메모리 해제
힙(Heap): 원시 자료형이 아닌 보다 큰 크기의 데이터를 담고자 동적으로 할당하는 메모리 공간

동적 할당(dynamic allocation): 힙 영역에 필요한 만큼의 메모리 공간 할당 -> 더 이상 필요하지 않으면 메모리 해제

  • 상황에 따라 원하는 크기의 메모리 할당 가능(malloc, calloc), 이미 할당된 메모리라도 언제든지 크기 조정 가능(realloc)
  • 그러나 C언어의 경우 GC(garbage collector)가 없기 때문에 개발자가 명시적으로 메모리 해제(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

profile
📝 It's been waiting for you

0개의 댓글