메모리 동적 할당

메모리 정/동적 할당의 개념과 동적할당함수의 기능과 사용법, 메모리 관리 함수.

  • 학습 목표
    1. 메모리 정적할당과 동적할당의 이해.
    2. 메모리 동적할당함수를 이용하여 프로그램 작성.
    3. 메모리 관리함수의 기능 이해.

주요 용어

  • 데이터 영역 : 전역변수와 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));
  #include <stdio.h>
  #include <stdlib.h>

  void main()
  {
    int i;
    int *a;

    // int형 크기의 기억공간 5개 할당.
    a = (int *)calloc(5, sizeof(int));

    for (i = 0; i < 5; i++)
    {
      //  0으로 초기화 되어 있음.
      printf("%d\n", a[i]);
    }

    free(a);
  }

realloc()

  • 이미 할당 받은 기억 공간의 크기를 변경해야 할 필요가 있을 때 사용.
  • 형식 : void * realloc( void *p, int size);
  • 기능 : 포인터 p가 가리키고 있는 기억공간의 크기를 지정된 size의 크기로 변경.
  int *a;
  //  int형 크기의 5개 기억공간 할당.
  a = (int *)calloc(5, sizefo(int));
  ...
  //  int형 크기의 10개 기억공간 재할당.
  a = (int *) realloc(a, 10 * sizeof(int));

기억공간 관리함수

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 반환.
  #include <stdio.h>
  //  기억공간 관리함수를 위한 헤더파일.
  // #include <mem.h>
  #include <memory.h>

  void main() {
    char *s1 = "aaa";
    char *s2 = "bbb";

    int stat;

    stat = memcmp(s1, s2, 3);

    printf("%d\n", stat);
  }

memcpy()

  • 기억 공간의 자료를 다른 기억 공간 영역으로 복사하기 위한 함수.
  • 형식 : void * memcpy( void *dest, const void * src, size_t n);
  • 기능 : src에서 n byte만큼 dest에 복사.
  #include <stdio.h>
  #include <memory.h>
  #include <string.h>

  void main()
  {
    char src[] = "1234567890";
    char dest[] = "abcdefghijklmnopqrstuvwxyz";
    char *stat;

    printf("BEFORE MEMCPY() DEST : %s\n", dest);

    //  src의 첫 부분에서부터 문자열의 길이(strlen())만큼의 자료를 dest에 복사.
    stat = (char *)memcpy(dest, src, strlen(src));

    if (stat)
      printf("AFTER MEMCPY() DEST : %s\n", dest);
    else
      printf("FAILURE ON MEMCPY()!");
  }
  //  BEFORE MEMCPY() DEST : abcdefghijklmnopqrstuvwxyz
  //  AFTER MEMCPY() DEST : 1234567890klmnopqrstuvwxyz

memset()

  • 기억 공간의 자료를 지정한 문자로 채우는 함수.
  • 할당된 기억 공간의 초기화나 내용 삭제를 위해 주로 사용.
  • 형식 : void * memset( void *s, int c, size_t n );
  • 기능 : 포인터 s가 가리키는 곳을 c 값으로 n byte 만큼 채운다.
  #include <stdio.h>
  #include <memory.h>
  #include <string.h>

  void main()
  {
    char s[] = "1234567890";

    printf("BEFORE MEMSET() : %s\n", s);

    //  배열 s의 데이커를 *로 길이 만큼 채움.
    memset(s, '*', strlen(s));

    printf("AFTER MEMSET() : %s\n", s);
  }

728x90
반응형

'Language > C' 카테고리의 다른 글

[C] 파일 처리 함수 - 2  (0) 2021.01.02
[C] 파일 처리 함수 - 1  (0) 2021.01.01
[C] 구조체와 공용체 - 2  (0) 2021.01.01
[C] 구조체와 공용체 -1  (0) 2020.12.27
[C] 배열과 포인터 - 3  (0) 2020.12.27

+ Recent posts