[메모리] Code, Data, Heap, Stack
코드영역
실행할 프로그램의 코드가 저장되는 영역 ( 텍스트 영역 )
프로그램이 시작하고 종료될 때 까지 메모리에 계속 남아있음
데이터 영역
프로그램의 전역변수와 정적(static) 변수가 저장되는 곳
----------------------------------------------------------------------------------------------------------
Static : 메서드나 필드가 클래스의 인스턴스가 아닌 클래스 자체에 소속되게 하는 한정자.
public static int a;
public int b;
이 둘의 차이점 : b는 클래스 인스턴스를 생성할 때마다 메모리에 매번 새로 생성되는 반면에
a는 프로그램 실행 후 해당 클래스가 처음으로 사용될 때 한번만 초기화 되어 계속 동일한 메모리 주소에 상주하게 됨.
그럼 왜 static 을 쓰냐?
static 필드는 프로그램 전체에 걸쳐 하나만 존재함. 그렇다면 프로그램 전체에 걸쳐 공유해야하는 데이터(변수, 함수) 가 있다면, static을 사용하면 됨. ( 게임 내에서 새로운 씬이 로드 되더라도 보존되야 하는 점수와 같은 변수를 유지할때 사용 à 실제로 LastDream에서 코인 개수를 static으로 사용했기 때문에 내 실사용이 이렇다 라고 설명 가능 )
그럼 어떻게 non-static과 static을 언제 사용해야할까?
객체 내부의 데이터를 이용해야 하는 경우에는 인스턴스 메서드를 사용하고
객체 내부 데이터를 이용할 경우가 없을 때는 인스턴스를 안만들고도 데이터를 호출 할 수 있게 static을 사용해야한다.
----------------------------------------------------------------------------------------------------------
힙 영역
프로그래머가 직접 공간을 할당하고 해제하는 메모리 공간이다.
malloc() 할당, free() 해제
FIFO 방식이므로 먼저들어온 데이터가 먼저 인출된다. 왜?? 힙 영역이 메모리의 낮은 주소에서 높은 주소의 방향으로 할당되기 때문
스택 영역
프로그램이 자동으로 사용하는 임시 메모리 영역.
함수 호출 시 생성되는 지역변수, 매개변수가 저장되는 영역이고
함수호출이 완료되면 사라짐
LIFO방식. 왜? 메모리의 높은 주소에서 낮은 주소 방향으로 할당되기 때문
OverFlow
영역이 넘처 흐른다는 뜻이다. 즉, 한정된 메모리 공간이 부족하다는 말인데.
잘 생각해보자. 코드와 데이터 영역은 크기가 변동이 크게 없다. 즉 런타임과 컴파일에 영향을 받지 않는 영역이다. 그렇다면 프로그래머와 프로그램이 직접 공간을 사용하는 공간이 바로 heap과 stack영역이다. 프로그래머, 프로그램이 공간할당을 비효율적으로 하거나 데이터를 너무 많이 쳐박으려 하면 각각 힙 오버플로우, 스택 오버플로우 가 일어나게 된다.
위 설명에도 있듯이 힙영역은 낮은주소->높은주소 메모리로 할당되고,
스택영역은 높은주소->낮은주소로 할당되기때문에 서로 침범할 수 있게 된다.
그렇다면 왜??????
힙영역은 낮->높 (ex 0x001 -> 0x010)이고
스택영역은 높->낮(ex 0x200 -> 0x150) 일까?
답은 간단하다. 프로그램 실행을 위해 OS가 프로그램의 정보를 메모리에 로드하는데 로드되는(프로그램에 할당된) 메모리의 크기는 한정적이다.
프로그램이 메모리에 로드된 이상 코드,데이터 영역은 크기가 변할 일이 없다.
그럼 유동적을 변할 수 있는 영역은 힙과 스택인데, 둘다 넉넉하게 공간을 줘야 프로그램이 효율적을 돌아갈 텐데
“넉넉하게” 라는 기준을 어떻게 잡을 것인가?? 대충 절반 나눠서? 에이 안된다. 둘중 하나를 골라 더 주는것도 말이 안된다
"유동성"을 부여해줘야 한다.
그럼 이미 차지된 영역(코드, 데이터)을 제외하고 남은 영역을 둘이 자유롭게 사용하게 해야한다( 단, 최대한 오버플로우가 나지 않게 ).
힙 영역의 시작 지점을 코드, 데이터가 할당받은 메모리 주소의 그 다음 주소를 받게 해주고 영역의 마지막은 자유롭게 추가되게 하는거다.
스택 영역은 할당받은 메모리의 제일 큰 주소를 받고 스택영역이 커질 때마다 낮은 주소 방향으로 스택의 데이터가 메모리 주소를 할당받게 하는거다.
예를 들어서 설명하자면,
프로그램의 할당받은 메모리의 주소를 0x001 ~ 0x100 이라고 해보자.
Code 영역은 0x001 ~ 0x009 를 사용하고,
Data 영역은 0x010 ~ 0x019 를 사용하고 있다고 하자.
그럼 남은 메모리 주소들은 0x020 ~ 0x100이다.
이 89개의 주소들을 heap과 stack이 잘 나눠써야한다.
그럼 Heap은 0x020 부터 높은 메모리를 사용하게되고 ( 데이터가 추가 된다면 0x021, 0x022 ... 이렇게 할당 )
Stack은 0x100 부터 낮은 메모리를 사용하게 된다( 데이터가 추가된다면 0x099, 0x098 ...).