이 게시글은
서울대학교 데이터사이언스 대학원
조요한 교수님의
데이터사이언스 응용을 위한 컴퓨팅 강의를
학습을 목적으로 재구성하였습니다
Memory Model
메모리 모델이란
프로그래밍 언어에서
메모리를 관리하는 방식이다
아마 언어마다 각각의 메모리 모델이
다르겠지만, 이번 수업에서는
크게 python과 C언어에 대해서만
비교를 했다
python의 Memory Model
python의 메모리 모델은
high-level
comceptual diagram이다
파이썬은
위 다이어그램처럼 메모리를 관리하는데,
frame 한 개는
한 개의 scope이라고 보면 된다
python은 변수들의 정확한 memory location은
숨겨져있으며,
reference 형식으로 메모리를 참조한다
C언어의 Memory Model
사실 중요한 것은
c언어의 메모리 모델이다
c언어의 메모리 모델은
low-level
concrete diagram이다
저 오른쪽의 다이어그램이
굉장히 중요하다고 한다
c언어의 메모리 모델에는
4가지 섹션이 있는데
이 각각의 섹션에는
섹션의 용도에 맞게 데이터들이 저장된다
1) text section(program section)
c언어로 프로그램을 작성할 때
실제 코드가 저장되는 부분이다
2) global section
이 부분에는 흔히 전역변수라고 하는
글로벌 변수들이 저장된다
프로그램이 어디에서나 접근할 수 있는
변수들을 저장하는 부분이다
3)heap
dynamic하게 메모리를 할당할 때 저장한다
이 dynamic 하다는게 무슨 뜻이냐면
프로그래밍을 하다보면
변수를 할당하여 사용하거나
변수 사용이 끝나서 할당을 해제해야할 경우가 있는데
이러한 변수들을 담는 공간이다
프로그램에서 필요할 때 마다 할당할 때
heap에 데이터들을 할당한다
4) runtime stack
이 부분은 유저나 개발자가
마음대로 할당할 수 없는 부분이다
컴파일러가 코드를 보고 계산해서
변수를 저장하거나 할 때 할당하는 부분이다
자료구조의 stack처럼
데이터들이 할당되어서
rutnime stack이라고 부른다
Stack VS Heap
그렇다면 stack과 heap을 비교해보자
Stack(runtime stack)
stack에는 메모리가 할당될수록 낮은 address가 배정된다
현대의 아키텍처들은 모두 이런 방식이라고 한다
스택에 메모리를 얼만큼 할당할지는 컴파일러가 계산하는 것이며
개발자가 설정할 수 없다
주로 runtime stack에는 함수 내부의 변수같은
local variables들이 할당되며
컴파일러가 미리 계산을 해놓기 때문에
빠르고 효율적인 메모리 관리가 가능하다
빠르고 효율적인 메모리관리가 가능하다는 뜻은
연속적인 공간관리가 가능하다는 뜻인데,
fragment(단편화)
즉, 할당된 데이터와 데이터들 사이에
빈 공간이 없이 연속적으로
메모리 효율을 최대화하며
연속적으로 할당된다는 뜻이다
Heap
동적으로 데이터를 할당한다
동적으로 데이터를 할당한다는 뜻은,
개발자가 필요할 때마다 메모리를 할당하도록
설정할 수 있다는 뜻이다
프로그래머가 스스로 필요한 메모리를
allocation(할당)하고 사용이 끝났으면
deallocation(해제)할 수 있다
heap에 들어있는 데이터에 접근하기 위해서는
pointer변수를 사용한다
이러한 heap은 stack에 비해서
상대적으로 느리고 단편화(fragmented)되어 있고
데이터가 연속적으로 저장되지 않는다
이는 위의 stack과는 반대로
할당된 데이터와 데이터 사이에 빈 공간이 생겨
메모리를 효율적으로 관리하지못할 가능성이
크다는 뜻인데,
이러한 이유는 프로그래머가 동적으로 할당하는 부분은
어디에 어떤 데이터가 있다가 언제 사라질지
예측하기가 어렵기 때문에
중간중간에 불가피하게 낭비되는 메모리 공간이
생길 수 밖에 없는 것이다
C언어에서 heap에 데이터를 동적으로 할당할 때
사용하는 함수는
malloc function이며
int *ptr = malloc(sizeof(int));
와 같은 방식으로 할당한다
위 코드는 int 데이터를 가진
ptr이라는 포인터 변수의 주소값에
int 크기만큼의 메모리를 할당한다는 뜻이다
heap에 데이터를 동적으로 해제할 때
사용하는 함수는
free function이다
데이터가 메모리를 다 사용하고
더이상 해당 데이터를 사용할 일이 없을 때
free(ptr);을 통해서
ptr변수에 할당된 메모리 공간만큼이 해제되며
그 공간을 다른 데이터들을 위해 사용할 수 있게된다
heap에 메모리가 할당이 한 번 되면,
프로그램이 끝나거나 개발자가 해제할 때까지 계속 할당이 되어있어
메모리 공간 사용이 끝난 후에도 할당 해제를 해주지 않는다면
그 메모리 공간만큼은 프로그램이 끝날 때까지
이용을 할 수 없게되어 메모리 공간의 낭비가 발생한다
Memory Operation
그렇다면 c언어에서
여러 함수들을 call할 때
컴파일러가 어떤 식으로 데이터들을
runtime stack에 할당하고 할당을 해제하는지
구체적으로 알아보도록 하자
이런 c언어 코드를
컴퓨터에서 실행시켰다고 가정해보자
이 프로그램을 실행하면서
c언어는 어떻게 메모리들을
할당하고 해제할까?
우선 모두가 알겠지만
c언어에서 가장 먼저 실행되는 부분은
main 함수이다
프로그램의 entry 부분이라고 할 수 있다
가장 처음 main함수가 실행되면서
runtime stack에는
main함수를 위한 메모리가 할당된다
stack point는 지금 실행되고 있는 함수의 메모리 중
가장 윗 단을 나타내고
frame point는 가장 아랫단을 나타낸다
메모리의 젤 처음 부분인 stack point와
메모리의 젤 마지막 부분인 frame point로
현재 어디서부터 어디까지가
이 function을 위해 할당되어있는지를
tracking한다
이제 main함수의
b = Watt(a); 부분에서
Watt함수가 실행됐다
그렇다면 당연히 현재 실행 중인
Watt 함수에 대한 메모리 공간도
할당될 것이다
main이 할당된 메모리 위에
Watt 함수에 대한 메모리 부분이
할당되었다
이렇게 차곡차곡 쌓이는 자료구조를
stack이라고 부르며
stack에서 새로운 데이터가 들어가는걸
push됐다고 부른다
이 할당된 Watt 메모리 안에는
watt 함수의 실행이 끝났을 때
어디로 메모리가 돌아가야할지,
인자값은 어디에 있는지,
watt라는 함수안에서 새로 정의한 변수 w를 위한 공간도
watt영역 안에 저장된다
이 안에 저장되는 메모리는
watt라는 함수를 정상적으로 실행시키기위한
데이터들이 저장된다고 보면 된다
이제 실행되고 있는 Watt함수 안에서
Volt라는 함수가 호출되었다
그럼 아까 Watt와 마찬가지로
Volt 함수를 위한 메모리 공간도
Watt위에 stack 형식으로 push 될 것이다
이렇게 Volt함수까지 모두 실행되고
Volt함수의 실행이 끝났다
그럼 이제 Volt함수에 대한 메모리 공간은
필요가 없어지므로 할당을 해제해줘야된다
Volt함수의 실행이 끝나면
Volt함수에 대한 메모리 공간이 할당 해제된다
이러한 방식으로 데이터가 빠져나가는걸
stack구조에서는 pop되었다고 부른다
이렇게 Volt가 pop되면 Watt함수의
마지막을 가리키도록 포인터가 변경된다
그렇게 Watt함수의 실행도 끝나면
Watt함수의 메모리 공간도
할당이 해제되어 pop된걸 볼 수 있다
C언어에서 컴파일러는 이러한 방식으로
runtime stack에 메모리를 할당하고 해제한다
학생 질문 정리
Q) #include <stdio.h>와 같은 헤더파일에 대한 메모리는 어떻게 할당하고 해제하나요?
A) 메모리 모델에 program section이라고 소스코드를 저장하는 부분이 따로 있음
모든 코드들은 다 그곳에 저장됨
runtime stack은 실제로 실행을 하면서 변수들이 저장되는 곳임
header에서 호출한 부분이 현재 사용되고있지 않다면 runtime stack에는 저장되지 않음
만약 header파일이 호출되는 부분이 있으면 그때 runtime stack에 저장됨
Q) python은 어떤 방식으로 메모리를 관리하는지?
A) 큰 레벨에서 보면 c언어와 다르지 않으나, 파이썬은 이러한 메모리 할당 해제 과정을
stack이 아닌 heap에서 다루는걸로 알고있음
C언어 같은 경우는 코드를 미리 읽어서 파악하기 때문에 이런 방식의 할당이 가능하지만,
python같은 경우는 코드 전체를 미리 보지 않기 때문에 heap을 사용해서 동적으로 변수를 저장함
'강의 > computer science' 카테고리의 다른 글
[ComputerScience] C언어와 포인터 (3) | 2024.09.09 |
---|---|
[ComputerScience] 프로그래밍 언어 개요(python의 Module과 Class, 객체지향(OOP)의 4가지 원칙) (3) | 2024.09.06 |
[ComputerScience] 프로그래밍 언어 개요(변수, 데이터타입, 범위, 연산자) (2) | 2024.09.06 |
[ComputerScience] 인터프리터와 컴파일러 (0) | 2024.09.06 |
[ComputerScience] macOS에서 C/C++ 코딩 환경설정하기 (3) | 2024.09.05 |