일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 메모리 접근 충돌
- Github file size
- iOS 버전 점유율
- 대머리깃허브
- Dispatch.main.sync
- Ribs
- 로버트마틴형
- SWIFT
- memory safety
- conflicting access to memory
- swiftdocs
- App Signing
- 클린아키텍쳐
- coordinateSpace
- Large File Storage
- RxCocoa
- UICoordinateSpace
- Apple Certificate
- RIBs Tutorial
- iOS Target
- rib
- ios
- Git Large File Storage
- Automatically manage signing
- in-out
- 잡초가득블로그
- windowScene
- RxSwift
- Concurrent
- Dependency Rule
- Today
- Total
빙수왕의 개발일지
Memory Safety - #1 Conflicting Access to Memory 본문
Memory Safety
기본적으로, Swift는 코드에서 안전하지 않은 동작이 발생하는걸 방지해준다. 예를들어, Swift는 변수를 사용하기 전에 초기화하도록 하고, 할당 해제(dellocated)후 메모리에 접근하지 않도록 하며, Array indices에서 out-of-bounds error가 있는지 확인한다.
→ 변수 초기화를 안하면 컴파일 오류를 낸다던가, 해제된 메모리에 접근하거나 array out of index 에러 발생 시 런타임에 오류가 떨어지는 것을 말하는듯 하다.
Swift는 또한 동일한 메모리에 대한 다중 접근이 충돌(conflict)하지 않도록 한다.
어떻게? 메모리의 location을 수정하는 코드가 그 메모리에 단독으로 접근할 수 있도록 하는 방법으로.
→ 메모리의 위치를 수정할 경우 메모리에 락을 거는 방법일듯 함..
Swift는 메모리를 자동으로 관리하기 때문에 나는 대부분 메모리에 접근하는 것에 대해 생각할 필요가 없다. 그러나 잠재적인 confilct가 일어날 수 있는걸 이해하는건 중요하다. 메모리 접근 conflict가 있는 코드 작성을 피할 수 있도록 하기 때문이다. 만약 내 코드가 conflict를 포함한다면, 컴파일타임 에러나 런타임 에러가 발생할 것이다.
→ ARC 덕분에 꼭 생각하지 않아도 되지만, 암튼 충돌(conflict)가 발생할 수 있으니 알고 쓰는것이 좋다~~
이제 이 충돌에 대해 알아보자.
Understanding Conflicting Access to Memory - 메모리 접근 충돌 이해
메모리 접근 충돌
은 변수에 값을 set하거나 함수에 argument를 전달하는 등의 작업을 할 때 발생한다. 예를들어, 다음 코드에는 read와 write access 모두 있다.
코드의 여러 부분에서 메모리의 같은 위치에 동시에 접근하려고 할 때 메모리 접근 충돌
이 발생할 수 있다. 동시에 메모리의 location에 다중 접근하면, 예측 불가능하거나 일관되지 않는(inconsistent) 동작이 발생할 수 있다.
Swift에서는 여러 줄의 코드 행에 걸쳐 있는 값을 수정하여, 자체 수정(its own modification) 중에 값에 대한 접근을 시도할 수 있는 방법들이 있다. (In Swift, there are ways to modify a value that span several lines of code, making it possible to attempt to access a value in the middle of its own modification.)
→ 마지막줄이 이해가 잘 되지 않는다. 번역도 잘 안됨 ㅎㅎ;
암튼 뭔가.. 여러 군데에서 메모리에 동시에 접근할 때 충돌이 발생할 수 있지만, Swift에서는 수정 중에 있는 값에 접근하여 이 접근 충돌을 해결할 방법들이 있다???? 정도로 받아들였음.
종이에 쓰인 예산을 업데이트하는 방법을 생각해 보면 이와 비슷한 문제이다. 예산 업데이트는 두 단계로 이루어진다.
- 항목의 이름과 가격을 추가한 다음
- 현재 목록에 있는 항목을 반영하도록 총 금액을 변경한다.
업데이트 전후에 아래 그림과 같이 예산에서 원하는 정보를 읽고 정답을 얻을 수 있다.
예산에 항목을 추가하는 동안(1 동안), 일시적으로 잘못된 상태에 있다. 총 금액에 새로 추가된 항목들이 반영되어 있지 않기 때문이다. 항목을 추가하는 과정에서 총 금액을 읽으면 잘못된 정보를 가져온다.
이 예에서는 메모리 접근 충돌을 해결할 때 마주할 수 있는 문제를 보여준다.
다양한 해결방법이 있을 수 있을 수 있고, 항상 어떤 방법이 명확하게 옳지는 않다. 이 예에서, 원래 총 금액을 원하는지 아니면 업데이트된 총 금액을 원하는지에 따라 $5 or $320이 정답일 수 있다. 충돌을 수정하기 전에, 의도된게 뭔지부터 결정해야 한다.
concurrent 또는 멀티스레드 코드를 작성했다면, 메모리 접근 충돌은 익숙한 문제일 수 있다. 하지만, 여기서 설명하는 접근 충돌은 싱글 스레드에서 발생할 수 있으며 concurrent 또는 멀티스레드 코드를 포함하지 않는다. 싱글 스레드 내에서 접근 충돌이 있다면, Swift는 컴파일 타임이나 런타임에 에러를 발생시키는걸 보장한다. 멀티 스레드 코드에서, Thread Sanitier(직역하면 스레드 검사기)을 사용하면 스레드간의 접근충돌을 탐지할 수 있다.
Thread Sanitier에 대한 내용은 여기있다고 한다. (안읽어봤다)
https://developer.apple.com/documentation/xcode/diagnosing-memory-thread-and-crash-issues-early
Characteristics of Memory Access - 메모리 접근 특성
충돌하는 접근에서 고려해야 할 메모리 접근에는 3가지 특성이 있다.
- 접근이 read 인지 write인지
- 접근 기간
- 접근되는 메모리 location
특히, 다음 조건을 모두 충족하는 두 개의 접근이 발생할 경우 충돌이 발생한다.
- 적어도 하나는 write 접근 또는 nonatomic 접근이다.
- 메모리에서 동일한 location에 접근한다.
- 지속 기간(duration)이 겹친다.
일반적으로 read 와 write 접근의 차이는 명확하다. - 쓰기 접근은 메모리 위치를 변경하지만 읽기 접근은 변경하지 않는다.
- 메모리 내의 location은 어떤 것이 접근할 것인가를 나타낸다. (예를들어 변수, 상수 또는 프로퍼티)
- 메모리 접근 기간(duration)은 instantaneous이거나 long-term이다.
C atomic operation만 사용하는 연산은 atomic
이고, 그렇지 않은 연산은 nonatomic
이다. 이러한 함수의 목록은 stdatomic(3) man 페이지를 참조해라.
→ man 페이지? manual page인듯 ..
*https://www.unix.com/man-page/mojave/3/stdatomic/ (이해불가..)*
atomic operation은.. 운영체제에 나오는 개념인데... 조금 찾아봤다.
atomic이 원자성아닌가? 쉽게말해 원자처럼 더이상 쪼갤 수 없다 이말임. 어떤 operation이 있을 때, 그 operation에서 일어나는 작업은 다같이 실패하던지, 다같이 성공하던지 둘중 하나다.
어떤 액세스가 시작된 후 종료되기 전에 다른 코드를 실행할 수 없는 경우, 그 액세스는 instantaneous하다고 한다. 원래 두 개의 즉각적인(instantaneous) 액세스가 동시에 발생할 수 없다. 대부분의 메모리 액세스는 순간적(instantaneous)이다. 예를 들어, 아래 코드 목록의 모든 읽기 및 쓰기 액세스는 instantaneous하다.
하지만, long-term access라는 방법을 사용하면 메모리에 접근할 수 있다. 이것은 다른 코드의 실행에 걸쳐서 일어난다.
instantaneous access와 long-term access의 차이점은 long-term access가 시작된 후 ~ 종료되기 전 사이에 다른 코드가 실행될 수 있다는 점인데, 이를 overlap(직역하면 중복)이라고 한다.
long-term access는 다른 long-term access 및 instantaneous access와 overlap될 수 있다.
overlapping access는 주로 In-Out Parameter을 사용한 함수 및 메서드와, 구조체의 mutating method를 사용하는 코드에서 나타난다. long-term access를 사용하는 특정 종류의 Swift 코드는 *아래 섹션에서 설명하겠다.
→ sync와 async개념과 비슷하게 느껴진다. instantaneous를 sync, long-term access를 async처럼 생각하면 이해에 도움이 된다. long-term 접근이 실행중일 땐 다른 instantaneous나 long-term이 중첩해서 일어날 수 있고, 이걸 'overlap'이라고 한다. (아니라면 ㅈㅅ)
*다음 섹션들:
Conflicting Access to In-Out Parameters, Conflicting Access to self in Methods, Conflicting Access to Properties
→ 힘드니까 이건 다음 포스팅으로 넘기겠다.. 그럼 20000....
출처
https://docs.swift.org/swift-book/LanguageGuide/MemorySafety.html
'개발 > iOS' 카테고리의 다른 글
앱만들기 #2 - 스토리보드 삭제하기 (0) | 2021.08.15 |
---|---|
앱만들기 #1 - iOS Deployment Target 정하기 (0) | 2021.08.15 |
In-Out Parameters, 인아웃 파라미터에 대하여 (0) | 2021.08.02 |
RxSwift 테이블뷰 다시 바인드할 때 오류 (0) | 2021.07.08 |
info.plist 이동 후 해야할 작업 (0) | 2021.06.25 |