(Cs with python)-메모리(가상주소공간)

컴퓨터사이언스 부트캠프 with 파이썬 책을 공부하며 정리한 포스팅입니다.

개인 공부후 정리용으로 남기는 포스팅으로 내용상에 오류가 있을수 있습니다.

예제 코드는 Computer-Science 를 통해 실습하고 있습니다.


핵심개념

  • 가상 주소 공간(virtual address space)
  • 코드 세그먼트(code segment)
  • 데이터 세그먼트(data segment)
  • 스택 세그먼트(stack segment)
  • 힙 세그먼트(heap segment)

가상 주소 공간(virtual address space)

  • 프로세스가 생성되면 실행되는 순간 4GB 메모리를 할당받음
    • 실제 메모리는 아니고 운영체제에게 4GB를 할당받은 것 처럼 사용.
  • 할당받은 4GB중 2GB는 운영체제가 담당하는데 커널 영역이라고 하며
  • 나머지 2GB는 실제 프로그램이 담당하는데 이를 유저 영역이라고 한다.
    • 유저영역은 코드(Code), 데이터(Data), 스택(Stack), 힙(Heap) 세그먼트로 나뉜다

가상주소공간

  • 그림처럼 가장 낮은 주소(0x00000000)부터 가장 높은 주소(0x7FFFFFFF)까지 코드, 데이터, 힙, 스택 세그먼트 순서로 위치한다
  • 가장 높은 주소는 10진수로 2,147,483,647. 즉, 2GB
  • 화살표는 각 세그먼트가 확장하는 방향을 나타냄

코드 세그먼트(Code segment)

  • 프로그램의 인스트럭션이 저장되는 공간
    • 함수나 클래스 정의 코드는 인스트럭션으로 변환되어 하드디스크에 저장되어 있다가
    • 프로세스가 실행되면 가상 주소 공간의 코드 세그먼트에 올라감

데이터 세그먼트(Data segment)

  • 전역 변수가 저장되는 공간(C 언어의 static 지역 변수도 포함)
  • 전역변수는 프로세스가 실행될 때 데이터 세그먼트가 올라가고 프로세스가 종료될때 소멸
  • 프로그램이 실행되는 동안 계속 있으며 프로그래머가 생성시기나 소멸시기를 결정할수 없다

코드, 데이터 세그먼트의 공통 특징은 프로세스가 실행되기 전에 이미 그 크기를 알수 있다는 점


스택 세그먼트(Stack segment)

  • 지역 변수가 저장되는 공간
    • 함수를 호출했을 때 그 스택 프레임이 스택 세그먼트에 생성된다는 의미
    • 함수가 호출되면 그 함수의 스택 프레임이 스택 세그먼트에 생기고
    • 함수 실행 도중 다른 함수를 호출하면 다시 호출된 함수의 스택 프레임이 이전에 호출한 함수의 스택 프레임 위에 쌓이며 늘어난다
  • 계속 스택 프레임을 쌓아 나간다면?
    • 최대로 늘어날수 있는 크기는 기본값으로 1MB(프로그래머가 정하지 않는 경우)
    • 스택 프레임이 쌓이다 최대 크기를 넘어가면 스택 오버플로(Stack over flow)오류 발생

힙 세그먼트(Heap segment)

  • 프로그래머가 자유롭게 메모리를 할당하고 해제할 수 있는 공간
  • 함수 호출이 끝나도 힙 세그먼트에 할당한 메모리는 해제하지 않는 한 메모리 공간에 계속 남아있음.
  • 메모리 누수(memory leak)
    • 힙 세그먼트에 할당한 메모리를 해제하지 않아 메모리가 계속 남아있는 상황
  • 힙은 스택과 달리 늘어날 수 있는 최대 크기가 정해져 있지 않다는 점이 중요함.

힙 세그먼트 코드예시

// segment.cpp
#include <iostream>

// CODE
int add(int a , int b){		// #1
  return a + b;
}

int subtract(int a, int b){
  return a - b;
}

// DATA
int global_x = 10;		// #2

int main(void){
  //STACK
  int local_x = 20;		// #3

  // HEAP
  int * heap_x = (int*)malloc(sizeof(int));		// #4
  *heap_x = 30;
  free(heap_x);		// #5


  return 0;
}

  • #1
    • 함수 add를 정의
    • 함수정의는 컴파일을 거치면서 인스트럭션이되고 프로세스가 실행되면서 코드 세그먼트에 올라감
  • #2
    • 전역 변수로 선언된 global_x는 데이터 세그먼트에 올라감
  • #3
    • local_x는 메인함수의 지역 변수이므로 스택 세그먼트의 스택 프레임에 생성됨
  • #4
    • 힙 세그먼트에 4바이트의 메모리를 할당하는 코드
    • malloc() 함수는 인자로 받은 바이트 수만큼 힙 세그먼트에 메모리를 할당
  • #5
    • 메모리를 해제하는 코드
    • free() 함수는 할당된 메모리를 해제
  • 힙 세그먼트의 장점
    • #4, #5 처럼 메모리의 할당과 해제 시점을 프로그래머가 정할수 있다.
    • 할당한 메모리를 해제하지 않고 메모리 주소값을 참조나 리턴으로 전달하면
    • 언제 어디서든 접근할 수 있다.
  • 힙 세그먼트의 단점
    • 굉장히 느리다
      • malloc() 함수로 메모리 할당시 메모리가 들어갈 만한 충분한 공간을 찾는데
      • 메모리 공간이 부족하면 찾을 때까지 검색을 이어나감
    • 메모리 단편화 발생
      • 할당과 해제가 잦아 메모리의 빈 공간이 잘게 나눠짐
      • 총합은 충분하나 관련 데이터가 한데 모이지 못하고 멀리 떨어져 저장될수 있다
    • 메모리 단편화로 인한 캐시 미스(cache miss) 혹은 페이지 폴트(page fault) 발생으로 성능 악화
    • 메모리 누수
      • 코드예시의 메인함수에서 다른 함수를 호출하고 그 함수 안에서 힙 세그먼트에
      • 할당을 한 다음 지역변수 heap_x에 메모리 주소값을 저장했다고 가정
      • 호출된 함수의 실행이 끝나기 전에 메모리의 주소 값을 호출한 쪽에
      • 전달하지 않으면 함수 호출이 종료되면서 heap_x가 사라지고
      • 할당된 메모리에는 더 이상 접근할 수 없게 되어 메모리 누수가 발생.

Reference

더북(TheBook)

markgun 블로그

나무위키-캐시 메모리

Comments