Dynamic Memory - C

ShinMinChul·2024년 11월 18일

Programming Technique

목록 보기
2/7
post-thumbnail

개요

동적이다 라는 것은 런타임(runtime)에서 메모리를 동적으로 할당하기 때문에 동적(dynamic) 이라는 특징을 가진다. 그렇기에, 정적 메모리동적 메모리는 사용하는 방식이나 로직에서 큰 차이는 없다.

핵심적인 차이는 메모리가 할당되는 시점관리 방식에 있다. 실행 시점만 다를 뿐, 기본적으로 데이터에 접근하고 사용하는 로직은 동일하다.



구현

그렇다면 정적 언어인 C언어에서 동적 배열을 구현해보자.

구현과정에서 #include <stdlib.h>를 불러와, 동적 메모리 할당 함수 malloc,realloc,free 를 적극 사용할 것이다.



각 함수의 구조

  1. malloc Memory Allocation

메모리를 동적으로 할당하는 함수이다. 지정한 크기 만큼의 연속적인 메모리 공간을 할당하고, 해당 메모리의 시작 주소를 반환한다. 할당된 메모리의 초기값은 정의되지 않으므로 초기화가 필요하다.

  void *malloc(size_t size);

size : 할당할 바이트 크기 예( sizeof(int) * 10 ).
return : 성공 시 메모리의 시작 주소를 반환, 실패 시 NULL 반환.



  1. realloc Reallocate Memory

기존에 할당된 메모리 크기를 변경하는 함수이다. 기존 메모리 블록을 확장하거나 축소할 수 있다. 새로운 크기를 제공하면, 필요한 경우 메모리 블록을 이동시키고 데이터를 복사한다.

void *realloc(void *ptr, size_t size);

ptr : 기존에 할당된 메모리의 포인터
size: 새로운 메모리 크기 (바이트 단위)
return :성공 시 새 메모리 블록의 시작 주소, 실패시 NULL 반환.



  1. free Free Memory

동적으로 할당된 메모리를 해제하는 함수이다. 할당된 메모리를 더 이상 사용하지 않을 때 호출하여 메모리를 반환한다. 메모리를 반환하지 않으면 Memory Leak(메모리 누수)가 발생할 수 있다.

void free(void *ptr);

ptr : malloc or realloc 으로 할당된 메모리의 포인터
return : 없음

예시

#include <stdio.h>
#include <stdlib.h>

int main(){
	int initial_size = 5;
    int *arr = (int *)malloc(initial_size * sizeof(int));

    // 배열 초기화
    for (int i = 0; i < initial_size; i++) {
        arr[i] = i + 1;
        printf("%d ", arr[i]);
    }
}
  1. 배열의 초기 크기를 설정하여 malloc을 사용하여 동적 메모리를 할당한다. 그 다음에 배열의 초기 값을 설정하여 결과적으로 {1,2,3,4,5} 가 저장된다.



 int new_size = 10;
    arr = (int *)realloc(arr, new_size * sizeof(int)); // 크기를 10으로 확장

    // 새로운 값 추가
    for (int i = initial_size; i < new_size; i++) {
        arr[i] = i + 1;
    }
  1. 배열의 크기를 변경하기 위해 새 크기를 설정한 뒤, realloc 을 사용하여 기존 배열의 크기를 new_size 만큼 확장한다. 기존 데이터는 새로운 메모리 블록으로 복사된다.

    그 다음에 새로 추가된 배열에 요소를 추가하여 결과적으로 {1,2,3,4,5,6,7,8,9,10} 이 저장된다.



free(arr); // 메모리 해제
  1. malloc , realloc으로 할당된 메모리를 해제한다. 메모리를 해제하지 않으면, 프로그램 종료 후에도 해당 메모리가 반환되지 않아 Memory Leak(메모리 누수)가 발생할 수 있다.




Memory Leak 메모리 누수

일반적으로, 프로그램이 종료 시, 운영체제는 해당 프로세스가 할당된 모든 메모리를 자동으로 해제합니다. 그러나, 이는 동적 메모리 할다에서 발생한 문제와는 다르다.

프로그램 종료 시 메모리 처리

1. 프로그램 종료 시의 메모리 반환

  • 프로세스 종료 시, 운영체제는 해당 프로세스가 할당한 모든 메모리를 자동으로 해제합니다. 즉, 프로세스가 종료되면 스택 메모리, 힙 메모리, 코드 영역 등 모든 메모리 공간이 운영 체제에 의해 회수됩니다.

  • 따라서, 프로그램이 종료되면 malloc으로 할당한 메모리도 운영 체제가 회수하지만, 이 메모리 누수의 문제는 프로그램 실행 중에 발생합니다.



2. 메모리 누수와 프로그램 실행 중

  • 메모리 누수는 프로그램이 실행되는 동안, 할당한 메모리를 해제하지 않아서 계속해서 메모리 자원을 낭비하는 현상입니다. 이 상태는 프로그램이 종료될 때까지 계속해서 메모리 자원을 점유하게 됩니다.
  • 프로그램이 종료되면 메모리 누수 문제는 운영 체제에서 해결되지만, 그동안 누적된 메모리 사용량으로 인해 시스템 자원 부족이나 프로그램 성능 저하를 일으킬 수 있습니다.



실제로 일어나는 일

1. 프로그램 실행 중:

  • 메모리를 할당하고 해제하지 않으면, 해당 메모리는 계속 사용 중 상태로 남습니다. 이로 인해 시스템의 메모리가 점점 소모되고, 다른 프로그램이나 프로세스에서 사용할 수 없게 됩니다.

2. 프로그램 종료 후:

  • 프로그램이 종료되면, 운영체제는 해당 프로세스의 모든 메모리 자원을 회수합니다. 즉, free()를 호출하지 않아도 운영체제가 모든 메모리를 회수하여 시스템에서 다른 프로세스가 사용할 수 있게 됩니다.

결론

  • free()를 호출하지 않아도 프로그램이 종료되면 운영체제는 해당 프로세스의 메모리를 회수합니다.

  • 그러나 프로그램이 실행 중일 때 메모리 누수가 발생하면, 시스템 자원이 낭비되고, 이는 프로그램 성능 저하나 시스템 자원 부족을 일으킬 수 있습니다.

  • 그러므로 동적 메모리를 할당한 후에는 반드시 free()를 호출하여 메모리를 해제하는 것이 중요하며, 프로그램 실행 중에 메모리 자원을 낭비하지 않도록 해야 합니다.

profile
개발은 예술이며, 나는 예술가다.

0개의 댓글