프로그래밍 과정 중 메모리 접근 제공
효율적인 메모리 관리
메모리 보호
에 대한 기능을 제공한다.
메모리 구조
논리적 주소(=가상주소)
코드가 저장된 공간과 프로그램에서 사용하는 자료구조.
물리적 주소
적재하는 실제 주소. 메모리 칩이나 디스크 공간.
메모리 관리 장치(MMU)
논리적 주소 -> 물리적 주소
변환을 담당. 즉, 바인딩을 담당.
변환 방법으론 고정 분할, 동적 분할, 페이징, 세그멘테이션 등이 있다.
바인딩이란?
논리적 주소 -> 물리적 주소
를 매핑시켜주는 작업.
언제 변환하냐에 따라 바인딩 종류가 나뉨.
> 링커(linker)
>
>
> 컴파일러가 원시 코드를 파일로 생성하면 이 파일에 라이브러리와 다른 파일들을 결합.
>
> exe 같은 파일이 링커를 통해 생성.
>
> **로더(loader)**
>
> 지정 위치에서 시작하여 메모리에 프로그램을 배치. 흔히 얘기하는 로딩을 해주는 역할.
>
메모리에 적재될 위치를 컴파일러가 알 수 있는 경우
int a;
를 선언했을 때 a
라는 변수의 메모리 주소는 100
으로 설정할 때프로그램 전체가 메모리에 올라가야함
메모리 적재 위치를 컴파일 시점에 모르면 대체 가능한 상대 주소를 생성
0
번부터 시작된다고 가정한다.0
번을 기준으로 코드 상 주소를 0+100
, 0+200
으로 상대 주소를 만든다적재 시점(Load time)에 시작 주소를 반영하여 코드 상 상대 주소를 다시 재설정한다.
프로그램 전체가 메모리에 올라가야함
실행 시간(Running)까지 주소 바인딩(할당) 함
하드웨어(MMU: Memory Management Unit)의 도움이 필요
대부분 OS가 사용
연속 메모리 할당
Fixed Partitioning
Dynamic Partitioning
필요한 만큼 메모리를 할당하는 것.
초기에는 전체가 하나의 영역
프로세스를 어디에 배치해야하는가에 대한 방법론 필요
외부 단편화(External Fragmentation)의 문제가 생김
가변 분할 방식에서 메모리에 프로세스가 적재되고 제거되는 일이 반복되면서, 여유 공간이 충분함도 불구하고 이러한 여유 공간들이 조각으로 흩어져 있어(Scattered Holes) 메모리에 프로세스를 적재하지 못해 메모리가 낭비되는 현상
해결 방법
Buddy System
내부 단편화와 외부 단편화를 해결하기 위한 방법
현재는 virtual memory에 바탕을 둔 페이징과 세그멘테이션 방식때문에 자주 쓰이는 방식은 아님.
비연속(분산) 메모리 할당
메모리 공간이 연속적으로 할당되어야 한다는 제약조건을 없애는 메모리 관리 전략
분산 메모리에서는 프로세스가 메모리에 분산되어 올라가기 때문에 가상주소를 실제 메모리 주소로 매핑을 해야한다.
가상주소(Virtual address) = 논리주소(Logical address)연속된 메모리 할당을 한다고 가정한 주소.
실제주소(Real address) = 절대주소실제 메모리에 적재된 주소.
Fixed Partitioning : Paging
Dynamic Partitioning : Segmentation
개발자가 직접 관리
// 포인터 변수 a에 SomeClass의 인스턴스를 할당
SomeClass* a = new SomeClass();
// a라는 변수의 메모리를 해제
delete a;
**// 포인터 변수 a에 int 크기 만큼의 메모리를 할당
int* a = (int*)malloc(sizeof(int));
// a라는 변수의 메모리를 해제
free(a);**
GC(Garbage Collection)의 등장
Ex) Java, Javascript, Python
목적은 프로그램에서 더는 사용하지 않는 메모리를 삭제
삭제한 뒤에는 메모리를 압축하여 메모리 파편화를 방지.
방식
GC는 보통 동작할 때 모든 스레드를 멈춘뒤 작업하는데, 이를 보고 Stop The World라고 부름.
방법
1. Reference Counting
2. Mark And Sweep
javascript에서 사용하고 있는 방식
사용하지 않는 메모리를 표시(Mark)하고 삭제(Sweep)한다.
보통, GC Root라는 객체를 두고 이 객체에 연결된 메모리를 재귀적으로 탐색하며 사용여부를 판단한다.
GC Root는 스레드, 함수, 변수 등 코드상에 존재하는 다양한 객체들이다.
1. GC Root에서 연결된 노드들을 재귀적으로 탐색한다.
2. 탐색 된 메모리를 표시(Mark)한다.
3. 이후 표시되지 않은 메모리를 해제한다.
3. Scavenge
해제와 동시에 메모리 압축이 가능한 방법이다.
메모리 공간을 크게 두 공간으로 잡아, 한 공간에만 할당을 하고 이후 꽉 찼을 시 메모리를 옮기며 남아있는 메모리를 해제하는 방식
메모리의 추적 방식은 최상위 스택 포인터가 존재하는데, 이 스택 포인터와 연결된 메모리만 Reachable(사용한다)하다고 판단한다.
4. Generational
Ownership에 3가지 규칙
- Rust의 모든 값(value)은 owner
라 불리는 변수들을 갖고있다.
- 하나의 값은 하나의 owner
만 가질 수 있다.
- owner
가 scope 밖으로 나가게 되면 그 값도 사라진다.
scope 예시
{ // s는 아직 유효하지 않다. 호출시 Error
let s = "hello"; // 여기서부터 s가 유효하다.
// 여기서도 s는 유효하다.
} // 이제 s는 유효하지 않다. 호출시 Error
let s1 = String::from("hello");
let s2 = s1;println!("{}, world!", s1);
println!("{}, world!", s1);
error[E0382]: use of moved value: 's1'
Swallow copy
가 아니라 move
라고 표현.deep copy
를 하지 않는다. 때문에 자동복사가 일어나는 곳에서도 런타임 퍼포먼스에 영향을 받을 걱정은 하지 않아도 된다.함수의 Ownership
fn main() {
let s = String::from("HELLO"); // 변수 s가 문자열의 owner가 됨
print_data(s); // 변수 s가 파라미터로 전달되면서 소유권이 move됨.
// 여기서부터는 변수 s 사용 못함.
}
fn print_data(data: String) { // 파라미터 data가 문자열의 새 owner가 됨
println!("{}", data); // 문자열 사용
} // 여기서 문자열 메모리 drop 함
--------------------------------------------------------------------------------
fn main() {
let mydata = get_data(); // 함수 리턴값을 받으면서 소유권 받음
println!("{}", mydata);
}
fn get_data() -> String {
let s: String = "Data".to_owned(); // 변수 s가 owner
s // 리턴하면서 소유권 이전
}
--------------------------------------------------------------------------------
fn main() {
let s1 = String::from("hello");
let s2 = s1;
let (s2, len) = calculate_length(s2);
println!("The length of '{}' is {}.", s2, len);
}
fn calculate_length(s: String) -> (String, usize) {
let length = s.len(); // len() returns the length of a String
(s, length)
}
Drop
함수가 자동으로 호출된다. 이 때 메모리 해제가 이루어진다.String
타입과 같이 할당 받을 메모리의 크기가 정해져 있지 않은 타입들에 대해서만 적용된다.추가적인 기능
참고
https://codingcoding.tistory.com/211
https://technote-mezza.tistory.com/92
https://techblog-history-younghunjo1.tistory.com/511
https://velog.io/@jisoolee11/메모리-관리
https://velog.io/@sawol/메모리-관리
https://daeun28.github.io/컴퓨터공학-스터디/post18/
https://deepu.tech/memory-management-in-programming/
https://kimchunsick.me/2022-01-21-memory-management-method/
https://boiler.buzzni.com/2017/02/27/ios-reference-count.html
https://inpa.tistory.com/entry/JAVA-☕-가비지-컬렉션GC-동작-원리-알고리즘-💯-총정리
https://www.linkedin.com/pulse/rust-memory-safety-how-prevents-common-memory-related-prabhat-/
https://open-support.tistory.com/entry/Rust-에서-메모리-관리가-장점인-이유의-예제-소스
https://medium.com/@kwoncharles/rust-러스트의-꽃-ownership-파헤치기-2f9c6b744c38
좋은 정보 감사합니다