오늘의 인기 글
최근 글
최근 댓글
Today
Total
12-27 00:09
관리 메뉴

우노

[Memory] 코드, 데이터, 스택, 힙 영역 본문

Operating System/Concept

[Memory] 코드, 데이터, 스택, 힙 영역

운호(Noah) 2021. 8. 18. 16:31

C언어의 메모리 구조

  • 프로그램을 실행시키면, 운영체제는 우리가 실행시킨 프로그램을 위해, 메모리 공간을 할당해줍니다.
  • 프로그램이 운영체제로부터 할당받는 대표적인 메모리 공간은 4가지입니다.
    1. 코드(code) 영역
    2. 데이터(data) 영역
    3. 스택(stack) 영역
    4. 힙(heap) 영역

메모리 영역 시각화

코드(Code) 영역

  • 코드(Code) 영역은, 실행할 프로그램의 코드가 저장되는 영역으로, 텍스트 영역이라고도 부릅니다.
  • CPU 는 코드 영역에 저장된 명령어를 하나씩 가져가서 처리하게 됩니다.

데이터(Data) 영역

  • 전역 변수static 변수가 할당되는 영역입니다.

  • 프로그램의 시작과 동시에 메모리에 할당되고, 프로그램이 종료되면 메모리에서 소멸됩니다.

  • 예제 코드

      #include <stdio.h> 
    
      int a = 10; // 데이터 영역에 할당 
      int b = 20; // 데이터 영역에 할당 
    
      int main() { 
          ... 
          return 0; 
      }
    • 위와 같은 프로그램 실행 시,
    • int형 변수 a, bmain 함수가 호출되기 전에 데이터 영역에 할당됩니다.
    • 때문에, 프로그램이 종료될 때까지 메모리상에 존재합니다.
      • 전역변수가 프로그램이 종료될 때 까지 존재하는 이유
  • 예제 코드 시각화

스택(Stack) 영역

  • 함수 호출 시 생성되는 지역 변수매개 변수가 저장되는 영역입니다.

  • 함수 호출이 완료되면 사라집니다.

  • 예제 코드

      #include <stdio.h> 
    
      void fct1(int); 
      void fct2(int); 
    
      int a = 10; // 데이터 영역에 할당 
      int b = 20; // 데이터 영역에 할당 
    
      int main() { 
    
          int i = 100; // 지역변수 i가 스택 영역에 할당 
    
          fct1(i); 
          fct2(i); 
    
          return 0; 
      } 
    
      void fct1(int c) { 
          int d = 30; // 매개변수 c 와 지역변수 d 가 스택영역에 할당 
      } 
    
      void fct2(int e) { 
          int f = 40; // 매개변수 e 와 지역변수 f 가 스택영역에 할당 
      }
    • main 함수fct1, fct2 라는 함수를 추가하였습니다.
    • a, b 를 데이터 영역에 할당한 뒤
    • main 함수를 호출하면
    • int형 변수 i 는 지역변수로서 스택영역에 할당됩니다.
    • 이후, fct1() 이라는 함수를 호출하면서, fct1 함수의 매개변수인 cd 가 스택영역에 할당됩니다.
    • fct1() 이라는 함수호출이 끝나면 cd 는 스택영역에서 삭제되며,
    • 이후, fct2() 라는 함수를 호출하면서, 매개변수 e 와 지역변수 f 가 스택영역에 할당됩니다.
    • 스택영역은 그 이름그대로 스택의 성질을 띄고있습니다.
      • 후입선출 구조
        • 가장 늦게 저장된 데이터가 가장 먼저 인출됩니다.
  • 예제 코드 시각화

힙(Heap) 영역

  • 필요에 의해 동적으로 메모리를 할당 할 때 사용합니다.

힙 영역은 왜 필요할까?

  • 코드 영역, 데이터 영역, 스택영역만 있으면 프로그램이 문제 없이 실행될 것 처럼 보입니다.

  • 그렇다면, 힙영역은 왜 필요한 것일까요?

  • 또한, 힙 영역은 프로그래머가 할당한다고 되어있는데,

  • 언제 할당을 해야하는 걸까요?

  • 배열을 예로 들어서 설명 하겠습니다.

      int main() { 
    
          // 정상적인 배열선언 
          int arr[10]; 
    
          // 비 정상적인 배열선언 
          int i = 0; 
          scanf("%d", &i); 
          int arr[i]; 
    
          return 0; 
      }
    • 배열의 길이를 사용자가 입력한 숫자로 잡아주는 것을, 비 정상적인 배열선언이라고 합니다.
    • 왜 비 정상적일까요?
    • 메모리 구조에 대해서 잘 파악하고 있다면 당연한 이야기입니다.
    • 상단의 첫번째 그림을 다시보면,
    • 스택 영역에 할당될 메모리의 크기는 컴파일 하는 동안 결정됩니다.
      • 컴파일
        • 개발자가 작성한 소스코드를 컴퓨터가 이해할 수 있는 기계어로 변환하는 작업
      • 런타임
        • 소스코드 파일을 실행가능한 소프트웨어 산출물로 만드는 일련의 과정
    • 정상적인 배열 선언의 경우,
      • arr 이라는 배열의 크기가 40바이트 라는것을 알 수 있으며,
      • 컴파일 과정에서, 미리 스택 영역에 arr 배열 영역을 할당해놓을 수 있습니다.
    • 하지만 비 정상적인 배열선언의 경우,
      • i 의 크기가 4바이트 라는 것을 알 수는 있으나, arr 라는 배열의 크기는 알 수 없어
      • 스택 영역에 arr 배열 영역을 할당해놓을 수 없습니다.
  • 그렇다면, 아래와 같이 배열을 선언할 때는 문제가 없을까요?

      int main() { 
    
          int i = 10; 
          int arr[i]; 
          return 0; 
    
      }
    • i 라는 변수가 10 이기 때문에, arr 라는 배열의 크기가 10 이라는 것을 알 수 있지 않을까요?
    • 결과는 아닙니다.
    • 컴파일을 하는 동안 i4바이트의 크기라는 것을 알 수는 있으나,
    • 그 값이 10 으로 초기화 되었다는 사실은 무시하고 넘어갑니다.
      • 값이 10 으로 초기화 되었다는 사실은, 실행되는 동안(런타임)에 결정됩니다.
    • 그렇기 때문에, 컴파일러는 arr 의 크기가 40바이트가 된다는 사실을 알 수 없으며,
    • 스택 영역에 arr 배열 영역을 할당해놓을 수 없습니다.
    • 따라서, 사용자의 요구에 맞게 arr 배열 메모리를 할당해 주기 위해서는
    • 메모리 동적 할당을 통해, 힙 영역에 arr 배열 메모리를 할당해야합니다.
      • 힙 영역
        • 할당해야 할 메모리의 크기를, 프로그램이 실행되는 동안 결정해야 하는 경우(런 타임때) 유용하게 사용되는 공간
    • 힙 영역을 사용하기 위해서는 동적할당에 대해서 공부해야합니다.

참고

Comments