컴퓨터사이언스 부트캠프 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가 사라지고
- 할당된 메모리에는 더 이상 접근할 수 없게 되어 메모리 누수가 발생.
- 굉장히 느리다
Comments