카테고리 없음

컴퓨터구조론 (코드 실행 메모리 구조)

hhenyy 2023. 12. 25. 23:08

메모리의 구조

프로그램이 실행되기 위해서는 먼저 프로그램이 메모리에 로드(load)되어야 한다.
메모리가 올라가지 않은 상태는 그저 코드 덩어리일 뿐..

메모리가 올라간다는 것은 코드의 부분부분에 적당한 메모리가 할당이 된다는 말이다.

따라서 컴퓨터의 운영체제는 프로그램의 실행을 위해 다양한 메모리 공간을 제공하고 각각의 메모리 공간은 상호작용하며 프로그램 실행에 기여한다.

프로그램이 운영체제로부터 할당받는 대표적인 메모리 공간은 다음과 같다.


1) 코드(code) 영역: 실행할 프로그램의 코드
2) 데이터(data) 영역: 전역 번수, 정적(static) 변수
3) 스택(stack) 영역: 컴파일 타임에 크기가 결정됨
4) 힙(heap) 영역: 런타임시 크기가 결정됨(동적할당)

컴파일 타임: 소스코드가 실행가능한 기계어코드로 변환되어 머신에서 실행가능한 프로그램이 되며, 이러한 편집과정을 컴파일 타임이라고 한다.
런타임: 컴파일 과정을 마친 프로그램이 사용자에 의해 실행되고 이러한 응욜프로그램이 동작되는 시점을 런타임이라고 한다.


1) 코드(code) 영역

메모리의 코드(code) 영역은 실행할 프로그램의 코드가 저장되는 영역으로 텍스트 영역이라고도 불린다.
CPU는 코드 영역에 저장된 명령어를 하나씩 가져가서 처리한다.

2) 데이터(data) 영역

메모리의 데이터(data) 영역은 프로그램의 전역 번수와 정적 변수(static)가 저장되는 영역이다.
데이터 영역은 프로그램의 시작과 함께 할당되며, 프로그램이 종료되면 소멸한다.

3) 스택(stack) 영역

메모리의 스택(stack) 영역은 함수의 호출과 관계되는 지역 변수와 매개변수가 저장되는 영역입니다.
스택 영역은 함수의 호출과 함께 할당되며, 함수의 호출이 완료되면 소멸한다.

스택 영역은 푸시(push) 동작으로 데이터를 저장하고, 팝(pop) 동작으로 데이터를 인출한다.
이러한 스택은 후입선출(LIFO) 방식에 따라 동작하므로, 가장 늦게 저장된 데이터가 가장 먼저 인출된다.
스택 영역은 메모리의 높은 주소에서 낮은 주소의 방향으로 할당된다.

4) 힙(heap) 영역

메모리의 힙(heap) 영역은 사용자가 직접 관리할 수 있는 '그리고 해야만 하는' 메모리 영역이다.
힙 영역은 사용자에 의해 메모리 공간이 동적으로 할당되고 해제된다.
객체의 참조값(Object Reference)이 이 힙 영역에 저장되는 대표적인 데이터이다.
흔히 자바에서 사용하는 class와 그 class 객체들은 이곳에 저장된다.
힙 영역은 메모리의 낮은 주소에서 높은 주소의 방향으로 할당된다.

메모리 간 상호작용(Java의 Stack과 Heap)

스택 영역과 힙 영역은 사실상 같은 공간을 사용한다.
그래서 스택 영역이 클 수록 힙 영역이 작아지고, 힙 영역이 클 수록 스택 영역이 작아진다.

스택 영역이 높은 주소 → 낮은 주소로 할당되고, 힙 영역이 낮은 주소 → 높은 주소로 할당되기 때문에 자신의 영역이 상대의 영역을 침범하는 사태가 발생할 수 있다. 이를 각각 스택 오버플로우, 힙 오버플로우 라고 한다.

1) Stack

Heap 영역에 생성된 Object 타입의 데이터 참조값이 할당된다.
원시타입의 데이터가 값과 함께 할당된다. 원시타입의 데이터는 Heap 메모리에 할당되지 않는다.
원시타입: byte, short, int, long, double, float, boolean, char 타입
지역변수들은 scope에 따른 visibility를 가진다.
각 Thread는 자신만의 stack을 가진다.

2) Heap

Heap 영역에는 주로 긴 생명주기를 가지는 데이터들이 저장된다(대부분의 객체는 크기가 크고 서로 다른 코드블럭에서 공유되는 경우가 많다.).
애플리케이션의 모든 메모리 중 stack에 있는 데이터를 제외한 부분이라고 보면 된다.
모든 Object 타입(Integer, String, ArrayList, ...)의 참조값은 데이터 타입과 함께 heap 영역에 생성된다.

자바에서 Wrapper class에 해당하는 Integer, Character, Byte, Boolean, Long, Double, Float, Short 클래스는 모두 Immutable(변경불가능)이다. Wrapper class는 아니지만 String 클래스 역시 Immutable하므로 heap에 있는 같은 오프젝트를 레퍼런스하고 있더라도 새로운 연산이 적용되는 순간 새로운 객체가 heap에 재할당된다.
새로운 객체가 heap에 할당되더라도 stack에서 이를 참조하지 않으면 가비지 컬렉션의 대상이 된다.
Heap 영역에 있는 객체들을 가리키는 참조 변수는 stack에 올라가게 된다.

참고

https://velog.io/@goserimgoserimgo/%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B5%AC%EC%A1%B0#:~:text=%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%82%98%20%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%EC%9D%84%20%EC%A0%80%EC%9E%A5,%EC%9C%BC%EB%A1%9C%20CPU%EC%99%80%20%EB%A9%80%EC%96%B4%EC%A7%84%EB%8B%A4.

http://www.tcpschool.com/c/c_memory_structure

https://velog.io/@jack2ee/CS-%EC%BB%B4%ED%93%A8%ED%84%B0-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B5%AC%EC%A1%B0-%EB%B0%8F-%EA%B4%80%EB%A6%AC