-
[iOS/OS] 메모리 구조Apple🍎/iOS 2024. 8. 23. 17:46
메모리
운영체제가 위처럼 보조기억장치(HDD)에서 프로그램 정보를, 메모리 program code 영역에 로드한다.
이후 CPU는 프로그램 코드에 있는 메모리를 관리하면서 명령어를 실행한다.위의 RAM(흔히 메모리) 안에는 코드, 데이터, 스택, 힙 이렇게 4가지 영역으로 나뉜다.
운영체제는 RAM에서 각각의 영역을, 프로그램이 실행될 때 얼만큼 프로그램에 할당할 것인지를 결정한다.
운영체제는 각 프로그램을 “프로세스”로 관리한다.
각 프로세스에 대해 가상 메모리 공간을 제공하고 이 공간은 해당 프로세스만이 사용할 수 있는 고유한 메모리 주소 범위를 가진다.가상 메모리
각 프로그램이 자신만의 독립된 메모리 공간(가상 주소 공간)을 가지고 있다고 느끼게 하는 것이다. 실제로는 RAM에 프로그램이 필요한 데이터, 코드를필요한 만큼만 할당하고, 나머지는 디스크의 스왑영역에 저장했다가 필요할 때 불러온다. 가상 메모리 기법은 물리적 메모리보다 더 큰 메모리 공간을 사용할 수 있게 하며, 디스크의 일부를 메모리처럼 사용하는 방법으로 구현된다.가상 메모리 기법으로 운영체제는 각 프로그램에 필요한 만큼 메모리를 할당하며,
각 프로그램은 코드, 데이터, 스택, 힙 등으로 구성된 고유한 메모리 영역을 갖고 있다.4가지 영역 구조
코드 영역(Code)
실행할 프로그램의 코드가 저장되는 text 영역
CPU가 코드 영역에 저장된 명령어를 하나씩 가져가서 처리한다.
코드 영역에는 함수의 정의, 실행 코드가 저장된다.데이터 영역(Data)
프로그램의 전역 변수, 정적(static) 변수가 저장되는 영역
프로그램의 시작과 함께 할당되며, 프로그램이 종료되면 소멸한다.스택 영역(Stack)
- 함수 호출과 관련된 지역변수, 매개변수, 리턴 주소 등아 저장되는 영역이다.
- 스택 영역은 함수를 호출할 때, 그 함수를 영역에 할당하고 함수가 return 되면 스택 영역에서 함수 부분이 메모리 해제된다.
- 스택 영역에 저장되어있는, 함수의 호출 정보를 스택 프레임(stack frame)이라고 한다. (C언어)
- 스택 영역은 후입선출(LIFO) 방식으로 동작하므로, 가장 늦게 저장된 데이터가 가장 먼저 인출된다.
스택 프레임
- 함수가 실행되면, 함수별로 스택 프레임이 생성된 후 → Stack 영역에 저장된다.
- 지역 변수의 값이 Int, Float, Double 등의 데이터형은 직접 스택 프레임내에 저장된다.
- 함수의 매개변수가 없더라도 다음 공간 지정을 위해 공간은 할당해놓는다.
힙 영역(Heap)
- 사용자가 직접 관리할 수 있고, 해야만 하는 메모리 영역이다.
- 사용자에 의해 직접 메모리 공간이 동적으로 할당되고 해제되는 영역이다.
(Swift에선 ARC & Garbage collection으로 알아서 해주지만)
메모리 할당
컴파일 타임은 프로그램 실행 전에 결정되는 반면, 런타임은 프로그램이 실행되는 동안 동적으로 할당된다.
- 컴파일 타임: 코드, 데이터 영역의 크기가 결정된다.
- 런 타임: 스택, 힙 크기가 동적으로 할당되고 결정된다.
실행 예시
아래 코드를 예시로 보면,
main() 함수에서 Person 1명의 나이에 5를 더해서, 5년 뒤 나이를 구하는 동작을 하려고 한다.
(명령어 1줄은 4바이트라고 가정한다)import Foundation func addNumbers(a: Int, b: Int) -> Int { return a + b } // 힙 영역: 클래스나 클로저 같은 참조 타입의 동적 할당 class Person { var name: String var age: Int init(name: String, age: Int) { self.name = name self.age = age } } // 스택 영역: 함수 호출 시의 지역 변수 func main() { let years: Int = 5 // 지역 변수 let person = Person(name: "John", age: 30) // 힙에서 가져오는 동적 변수 let result = addNumbers(a: years, b: person.age) // 지역 변수 print("\(person.name)의 5년 후 나이 = \(result)") } main()
main의 반환주소값은 만약 운영체제나 실행환경에서 실행했다면, 그 특정 위치의 주소를 가리킨다.
프로그램이 종료되는 경우, 운영체제에 의해 전체가 종료되면서 힙 영역의 메모리도 회수되지만,
만약 위의 Step3 처럼
종료되지 않고 계속 오래 실행된다면, 힙 영역의 메모리 누수(leak) 현상이 발생할 수 있다.이때 C에서는 free()로 malloc으로 할당된 영역까지 해제해주는 것이 개발자 영역이지만,
Swift에서는 ARC(Automatic Reference Counting)가 참조 카운트가 0이 되면 즉시 알아서 해제시켜준다.
(Swift 조타~)하지만 ARC도 강한 참조면 해제 못한다구?!
다음 ARC 글로 알아보자~'Apple🍎 > iOS' 카테고리의 다른 글
[iOS/SwiftUI] NavigationStack을 왜 사용하는가? (0) 2024.09.04 [iOS] ARC란 무엇인가 & 메모리 누수 (2) 2024.08.23 [iOS/UIKit] UICollectionViewLayout 정리 (1) 2024.05.17 [iOS] CoreData vs UserDefaults (0) 2024.04.15 [iOS] Cocoapods, Carthage, Swift Package Manager (0) 2024.04.15