25. 메모리 관리와 동적 할당

I. C 언어의 메모리 구조

  • 스택(Stack), 힙(Heap)그리고 데이터(Data) 영역

    • 메모리 공간은 스택, 힙, 데이터영역으로 나뉘어 진다.

      • 할당 시기 : 프로그램이 실행될 때마다
      • 할당 장소 : 메인메모리인 RAM
      • 할당 용도 : 프로그램 실행 시 필요한 메모리 공간의 할당을 위해
    • 데이터 영역(Data Area)

      • 전역 변수와 static 변수가 할당되는 영역이다. 이 영역에 할당되는 변수들은 일반적으로 프로그래의 시작과 동시에 할당되고, 프고르매이 종료되어야만 메모리에서 소멸된다.
    • 스택 영역(Stack Area)

      • 지역변수와 매개 변수가 저장되는 영역. 이 영역에 할당된 변수는 함수 호출이 완료되면 사라진다는 특징이 있다.
    • 힙 영역(Heap Area)

      • 프로그래머가 관리하는 메모리 영역이다. 필요에 의해서 메모리 공간이 할당 및 소멸되는 영역이다.

 

  • 프로그램의 실행과 메모리의 흐름
  1.  #include <stdio.h>
  2. void fct1(int);
    void fct2(int);
  3. int a = 10;
    int b = 20;
  4. int main()
    {
     int m = 123;
  5.  fct1(m);
     fct2(m);
  6.  return 0;
    }
  7. void fct1(int c)
    {
     int d = 30;
    }
  8. void fct2(int e)
    {
     int f = 40;
    }
  •  위의 소스가 메모리 상에서 어떻게 되는지 밑의 그림을 보고 이해해 보자.

    • 첫 번째 : 프로그램의 시작 그리고 전역 변수의 저장
    • 001.jpg 

      • 원래는 프로그램의 시작은 main부터 이겠지만 메모리에서는 main 보다는 전역변수가 먼저 데이터 영역에 올라가는 것이 먼저다.
    • 두번째 : main 함수의 호출
    •  002.jpg

      • 지역 변수인 m이 선언과 동시에 123으로 초기화 되었다.
      • 지역변수 m은 main 함수 내에서 선언된 지역 변수이므로 main함수가 완료 되기 전까지만 유효할 것이다.
    • 세번째 : fct1 함수의 호출
    •  003.jpg

      • fct1 함수 호출되면서 인자 m을 전달한다.  전달된 m은 fct1의 매개변수인 c가 선언되면서 123으로 초기화 된다.
      • fct1 함수내에 있는 지역변수 d도 선언되면서 30으로 초기화 된다.
    • 네번째 : fct1함수의 완료 그리고 fct2 함수의 호출
    • 004.jpg 

      • fct1 함수가 완료 되면 fct2가 호출되고 있는데 fct1의 스택공간은 지워져 버리고 fct2의 스택 공간이 할당된다.
    • 다섯째 : fct2 함수의 완료, main 함수의 완료 그리고 프로그램의 완료
    •  005.jpg

      • 먼저 fct2가 완료 되면 스택공간에서 지워지고 그다음 메인이 끝나기 때문에 메인부분이 사라진다. 그리고 전역변수로 선언된 것이 지워지면서 프로그램은 종료된다.

 

  • 배열은 반드시 상수로 선언해야 하는 이유

    • 배열 선언은 반드시 상수를 사용한다.
  1. #include <stdio.h>
  2. void function(int);
  3. int main()
    {
     int m = 0;
     scanf("%d",&m);
     function(m);
  4.  return 0;
    }
  5. void function(int i)
    {
     int array[i];
    }
  • 위의 소스가 관연 될까?

    • 당연히 안된다. 배열을 선언 할때 변수를 쓰면 안된다.

 

  • 배열 선언 시 반드시 상수만 써야 하는 이유

    • 스택과 데이터 영역에 할당될 메모리의 크기는 컴파일되는 동안에 결정되어야 한다.
  1. void function(int a)
  2. {
  3. int b;
  4. int c[2];
  5. }
  • 위의 소스는 메모리에 얼마나 할당을 받아야 할까?

    • 4(int) + 8(int * 2) 총 12바이트를 받으면 된다.
  1. void function()
  2. {
  3. int i = 10;
  4. int array[i];
  5. }
  •  위의 소스는 메모리에 얼마나 할당을 받아야 할까?

    • 4 + 40 = 44바이트를 받으면 된다.
    • 하지만 컴파일러는 4 + 4 = 8바이트를 받게 된다. 

      • 이유는 int i = 10을 보고 int 형이구나 구만 생각을 한다 그래서 초기화에 대한건 생각을 안한다.

 

II. 메모리 동적 할당

  • malloc 함수 & free 함수

    • malloc 함수

      • #include<stdilb.h> void* malloc(size_t size) : 함수 원형이며 할당하고자 하는 메모리의 크기를 함수 호출 시 바이트 단위로 전달하면 그 크기만큼 메모리를 힙에 할당하게 된다.
    • free 함수

      • #include<stdlib.h> void free(void* ptr) : 해제하고자 하는 메모리 공간을 가리키는 포인터를 인자로 전달하면, 해당 포인터가 가리키는 메모리 공간을 해제한다.
  1.  #include <stdio.h>
    #include <stdlib.h>
  2. int main()
    {
     int* a;
     a = (int*)malloc(sizeof(int));
  3.  if(a==NULL)
     {
      puts("메모리 할당에 실패");
      exit(1);
     }
     *a = 20;
     printf("힙에 저장된 변수 a : %d\n",*a);
  4.  free(a);
     return 0;
    }
  • 위와 같이 사용을 한다.
  1.  #include <stdio.h>
    #include <stdlib.h>
  2. void function(int);
  3. int main()
    {
     int m =0;
     fputs("배열의 크기를 입력하세요 : ",stdout);
     scanf("%d",&m);
     function(m);
     return 0;
    }
  4. void function(int i)
    {
     int* array = (int*)malloc(sizeof(int)*i);
     int j;
     if (array == NULL)
     {
      puts("메모리 할당에 실패");
      exit(1);
     }
  5.  for(j=0;j<i;j++)
      array[j] = j+1;
     for(j=0;j<i;j++)
      printf("%d",array[j]);
     printf("\n");
     free(array);
    }
  • 위의 소스는 앞전에 변수를 받아서 사용자가 배열의 크기를 결정짓게 하겠다는 소스이다.

 

  •  calloc 함수

    • #include<stdlib.h> void *calloc(size_t elt_count, size_t elt_size) : 함수 원형이며

      • malloc과 같은 역할을 한다. 다만 calloc은 할당받으면서 초기화를 해준다고 한다.

이 글은 스프링노트에서 작성되었습니다.

'2. C/C++ > 01. C' 카테고리의 다른 글

26. 매크로와 전처리기  (0) 2008.12.07
24. 파일 입.출력  (0) 2008.12.07
23. 구조체와 사용자 정의 자료형2  (0) 2008.12.07
22. 구조체와 사용자 정의 자료형1  (0) 2008.12.07
21. 문자와 문자열 처리 함수  (0) 2008.12.07
Posted by kid1412
,