본문 바로가기
스터디/CS & Network

메모리 구조를 알아보자.

by 헤콩 2020. 12. 10.
반응형

 

 

메모리 구조

운영체제는 프로그램의 정보를 읽어 메인 메모리에 공간을 할당해 로드한다. 이 메모리의 구조를 알아봅시다 ^_^..

velog.io

 

데이터나 프로그램을 저장하는 저장 공간은 계층 구조를 가집니다.

CPU에 접근속도가 빠른 순으로 Register, Cache, Main Memory, External Memory로 볼 수 있는데,

이 게시물에서는 메인 메모리의 공간 구조를 다룰 것입니다.

 

제가 메모리 구조에 대해 궁금해지게 된 것은 프로세스와 스레드의 차이점을 공부한 이후였습니다.

프로세스는 각 메모리 영역을 독립적으로 할당받고,

스레드는 Stack 영역만 독립적으로 할당받고 나머지 Heap, Data, Code 영역은 같은 프로세스 내의 다른 스레드와 공유한다는데 도대체 이 4가지 영역의 특징이 무엇일까?

하는 생각이 들었습니다.

 

그러니, Stack, Heap, Data, Code. 이 4가지 영역에 대해 한 번 알아보겠습니다 :)

 

 

 

이미지 출처 고림새^_^

 

Stack 영역

  • 함수의 호출과 관계되는 지역변수매개변수가 저장되는 영역입니다.
  • 함수의 호출과 함께 할당되며 함수의 호출이 완료되면 소멸합니다.
    • 이렇게 Stack영역에 저장되는 함수의 호출정보를 Stack Frame이라고 합니다.
  • 할당과 해제를 반복하기 때문에 데이터 용량이 불확실합니다. 프로그램이 자동으로 사용하는 임시 메모리 영역으로 생각할 수 있는데, 컴파일 시에 할당될 영역의 크기가 결정됩니다.
  • 메모리의 높은 주소부터 낮은 주소 순으로 할당되며, 낭비하는 공간 없이 영역을 사용하게 됩니다.
  • 다만, Stack영역은 정해진 크기를 넘어 할당할 수 없습니다.
    • 운영체제마다 Stack 영역의 제한된 크기가 다릅니다.

 

 

Heap 영역

  • 앞에서 설명한 Stack과 달리, 프로그램이 실행되는 동안 사용자에 의해 동적으로 할당되고 해제됩니다. 그렇기 때문에 런타임(=프로그램이 실행되는 중)에 Heap 영역의 크기가 결정됩니다.
  • Stack 영역과는 반대로 낮은 주소에서 높은 주소 순으로 할당된다.
  • class 같은 참조 타입의 데이터가 저장되며, Java의 경우 가비지 콜렉터가, Swift의 경우 ARC가 관리해주게 됩니다.

 

 

Stack 영역과 Heap 영역

  • 사실 상 Stack 영역과 Heap 영역은 같은 공간을 사용합니다.
  • 그래서 Stack 영역이 클 수록 Heap 영역이 작아지고, Heap 영역이 클 수록 Stack 영역이 작아집니다. (크기 반비례)
  • Stack 영역은 높은 주소 ➡️ 낮은 주소 순으로, Heap 영역은 낮은 주소 ➡️ 높은 주소 순으로 할당되기 때문에 서로 자신의 영역이 상대의 영역을 침범하는 사태가 발생할 수 있습니다. (같은 공간을 사용하니까)
    • Stack Overflow : Stack이 Heap 영역 침범
    • Heap Overflow : Heap이 Stack 영역 침범
  • Stack 영역에서 말하는 할당은 이미 생성된 공간에 대해 포인터의 위치만 바꿔주는 단순한 CPU Instruction이기 때문에 할당 속도가 빠릅니다.
  • Heap 영역에서 말하는 할당은 요청되는 양과 현재 메모리 상황 등 다양한 요소를 고려해야 하기 때문에 더 많은 CPU Instruction이 필요하여 Stack 보다 할당 속도가 느립니다.

 

 

Data 영역

  • 프로그램의 전역변수Static변수 등이 저장되는 영역으로, 프로그램 실행 시 전역변수와 Static변수는 메인 함수가 호출되기 전에 Data 영역에 할당됩니다.
  • 이렇게 할당된 데이터들은 프로그램이 실행되고 끝날 때까지 메모리에 남아있습니다.
  • Data 영역은 BSS 영역과 Data 영역으로 구분지어 말할 수 있습니다.
    • BSS (Block Stated Symbol)
      • 초기화되지 않은 변수가 저장됩니다.
      • 초기화된 데이터는 ROM의 Data 영역에 저장되는데, 아직 초기화되지 않은 데이터들까지 ROM에 저장되면 큰 사이즈의 ROM이 필요하기 때문에 BSS/DATA 영역을 나누어 저장합니다.
    • Data
      • 초기화가 이루어진 변수들이 저장됩니다.
      • 원래 Data 영역은 ROM에 위치하지만, 전역변수와 Static변수를 ROM에 저장하면 런타임시 변경된 값이 적용되지 않고 초기값만 가지게 되므로, RAM에 Data 영역을 복사하여 런타임시 변경되는 값을 저장할 수 있도록 합니다.
      • 따라서 프로그램 실행 중 접근/수정/변경이 가능합니다.

 

 

Code 영역

  • 사용자가 작성한 코드나, Read-Only 변수가 저장되는 영역으로, 컴파일 이후 기계어 형태로 저장됩니다.
  • 이렇게 저장된 데이터들은 프로그램이 실행되고 끝날 때까지 메모리에 남아있습니다.
  • Read-Only이기 때문에 수정이 불가합니다.

 

👉Code 영역 수정 불가 예시

#include <iostream>

int main() {
    char* words = (char*) "Hello, World!";
    // 이때 "Hello, World!"는 문자 리터럴이기 때문에 Code 영역에 저장된다.
    
    
    words[0] = 'h'; // Error -> Code 영역은 수정이 불가
}

 

 

 

 


이렇게 메모리 영역을 4가지 영역을 나누는 이유는 우리가 어떠한 프로그램을 구현할 때, 각각의 변수, 함수, 클래스 등이 호출되고 해제되는 시기가 다르기 때문입니다.

만약 어떠한 함수 내에서 한 번 사용되는 변수가 프로그램의 처음부터 끝까지 메모리에 남아있다면 메모리가 낭비되는 거겠죠?

또는, 어떠한 함수 내에서 값을 변경하고 함수가 끝나더라도 그 값을 유지했으면 좋겠는데, 만약 함수의 종료와 동시에 그 값이 메모리에서 사라진다면 안되겠죠?

그렇기 때문에 그런 변수들은 Stack메모리에 저장했다가 함수의 호출이 끝나면 내보내는 거죠 :)

반응형

'스터디 > CS & Network' 카테고리의 다른 글

Web의 동작원리  (0) 2021.01.04
DeadLock (교착 상태)  (0) 2020.12.21
버퍼, 캐시, 레지스터 (Buffer, Cache, and Register)  (0) 2020.10.03
커널 (Kernel)  (2) 2020.09.03
HTTP와 HTTPS  (4) 2020.07.27

댓글