์ƒˆ์†Œ์‹

๐Ÿ“ฑ iOS/-- UIKit

(iOS) ๋ฉ”๋ชจ๋ฆฌ ์ด์Šˆ ๋””๋ฒ„๊น…, ๋ฉ”๋ชจ๋ฆฌ ๊ทธ๋ž˜ํ”„ Xcode instrument, ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜

  • -

๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜(Memory leak)๋ž€ ?

retain cycle๋กœ ์ธํ•ด ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๊ฐ์ฒด๋ฅผ ํ• ๋‹น ํ•ด์ œํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ์— ๋ฐœ์ƒํ•œ๋‹ค. Swift๋Š” ARC๋ฅผ ํ†ตํ•ด ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๋ฅผ ํ•˜๋Š”๋ฐ, ๋‘ ๊ฐ์ฒด ์ด์ƒ์ด ์„œ๋กœ์— ๋Œ€ํ•ด ๊ฐ•ํ•œ ์ฐธ์กฐ๋ฅผ ํ•˜๋Š” ๊ฒฝ์šฐ์— retain cycle์ด ๋ฐœ์ƒํ•œ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ ์ฐธ์กฐ ์นด์šดํŒ…์ด 0์ด ๋˜์ง€ ์•Š์•„ deinit์ด ํ˜ธ์ถœ๋˜์ง€ ์•Š๋Š”๋‹ค.

์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด์„œ ๊ฐ์ฒด๊ฐ„์— ์ƒํ˜ธ์ฐธ์กฐํ•˜๋Š” ๊ฒฝ์šฐ weak, unowned ํ‚ค์›Œ๋“œ๋ฅผ ํ†ตํ•ด ์•ฝํ•œ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค.

(์ž์„ธํ•œ ๋‚ด์šฉ์€ ARC์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๋ฉด ๋œ๋‹ค.)

class A{
    var b: B?
}
class B{
    var a: A?
}
func makeMemoryLeaks(){
    let a = A()
    let b = B()
    a.b = b
    b.a = a
}

๊ฐ„๋‹จํžˆ ์˜ˆ๋ฅผ ๋“ค๋ฉด , a๋Š” ํด๋ž˜์Šค B์˜ ์ธ์Šคํ„ด์Šค์ธ b๋ฅผ ์ฐธ์กฐํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํด๋ž˜์Šค B์˜ ์ธ์Šคํ„ด์Šค b ๋Š” ํด๋ž˜์Šค A์˜ ์ธ์Šคํ„ด์Šค a ๋ฅผ ์ฐธ์กฐํ•˜๊ณ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ a, b๋Š” ๊ฒฐ๊ตญ ๋๊นŒ์ง€ ๋ ˆํผ๋Ÿฐ์Šค ์นด์šดํŠธ๋ฅผ 1๋กœ ์œ ์ง€ํ•˜๋ฉฐ ํ• ๋‹น ํ•ด์ œ๋˜์ง€ ๋ชปํ•œ์ฑ„ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ์–ด๋–ป๊ฒŒ ๋ฐœ๊ฒฌํ•  ์ˆ˜ ์žˆ์„๊นŒ?

์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ๊ฒ ์ง€๋งŒ, ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์„ ์ฐพ์•„๋ณด์•˜๋‹ค.

  1. Xcode - Memory graph debugger
  2. Instrument - Leaks

 

1. Xcode - Memory graph debugger

์„ค์ •

์‹คํ–‰ํ•˜๊ธฐ ์ „์— Edit Scheme๋กœ ๋“ค์–ด๊ฐ€์„œ Diagnostics ์„ค์ •์„ ์œ„ ์‚ฌ์ง„์ฒ˜๋Ÿผ ๋ฐ”๊พธ์–ด์ค€๋‹ค.

  • Live Allocation Only : All Allocations ๋ณด๋‹ค ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ์ ๋‹ค. ๋ฆฌํ…Œ์ธ ์‚ฌ์ดํด์ด๋‚˜ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ์‹๋ณ„ํ• ๋•Œ ํ•„์š”ํ•œ ํ•ญ๋ชฉ.

 

 

์‹คํ–‰

Xcode ์ฝ˜์†”์ฐฝ ์œ—๋ถ€๋ถ„์— ์•„๋ž˜ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๊ฒŒ ๋˜๋ฉด ์•ฑ ์‹คํ–‰์„ ์ค‘์ง€ํ•˜๊ณ  ํ˜„์žฌ ์ƒํƒœ์˜ ํž™์— ๋Œ€ํ•ด ์Šค๋ƒ…์ƒท์„ ์ฐ๋Š”๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‚จ์•„์žˆ๋Š” ๊ฐ์ฒด๋“ค๊ณผ ๋ฉ”๋ชจ๋ฆฌ์— ์œ ์ง€๋˜๊ณ  ์žˆ๋Š” ์ฐธ์กฐ ์ฒด์ธ์ด ํ‘œ์‹œ๋œ๋‹ค.

์ขŒ์ธก์— ํž™์— ์žˆ๋Š” ๊ฐ์ฒด ๋ฆฌ์ŠคํŠธ๋“ค์ด ๋‚˜ํƒ€๋‚œ๋‹ค. ์ธ์Šคํ„ด์Šค ์ด๋ฆ„, ์ธ์Šคํ„ฐ์Šค์˜ ๊ฐœ์ˆ˜, ๊ทธ๋ฆฌ๊ณ  ์ธ์Šคํ„ด์Šค์˜ ์ฃผ์†Œ๊ฐ’ ๋“ฑ์ด ํ‘œ์‹œ๋œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋ณด๋ผ์ƒ‰ ๊ฒฝ๊ณ ํ‘œ์‹œ๋Š” ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜์— ๋Œ€ํ•œ ๊ฒฝ๊ณ ์ด๋‹ค. ์•„๊นŒ ํด๋ž˜์Šค A, B๋ฅผ ์„œ๋กœ ์ƒํ˜ธ์ฐธ์กฐ ํ•˜๊ฒŒํ•˜์˜€๋”๋‹ˆ Xcode๊ฐ€ ๊ฐ์ง€ํ•˜๊ณ  ์•Œ๋ ค์ฃผ๋Š” ๋ชจ์Šต์ด๋‹ค.

์ค‘์š”ํ•œ ์ ์€ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋Š” Xcode๊ฐ€ ์ž๋™์œผ๋กœ ์ฐพ์•„์ฃผ๋Š” ๊ฒฝ์šฐ ๋ณด๋‹ค ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ์ฐพ์•„์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋” ๋งŽ๋‹ค. ์‹ค์ œ๋กœ ๋ช‡๊ฐœ์˜ Retain cycle์„ ๋งŒ๋“ค์–ด ํ…Œ์ŠคํŠธ ํ•ด ๋ณด์•˜๋Š”๋ฐ, ์ž๋™ ๊ฐ์ง€๊ฐ€ ์•ˆ๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋” ๋งŽ์•˜๋‹ค. ํ•ด๋‹น ์ฝ”๋“œ๋Š” ๊ฒŒ์‹œ๊ธ€ ํ•˜๋‹จ์— git๋ ˆํฌ์— ์žˆ๋‹ค.

A (3)
	0x60000210c5a0
	0x6000010c05a0
	0x6000020c13a0

๊ฐ์ฒด (์ธ์Šคํ„ด์Šค์˜ ๊ฐœ์ˆ˜)
	์ธ์Šคํ„ด์Šค์˜ ์ฃผ์†Œ

 

 

Object references

๊ฐ์ฒด๋ฅผ ํด๋ฆญํ•˜๋ฉด ์œ„์™€ ๊ฐ™์€ ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„๋“ค์ด ๊ทธ๋ฆผ์œผ๋กœ ๋‚˜ํƒ€๋‚œ๋‹ค.

๊ตต์€์„  → ๊ฐ•ํ•œ ์ฐธ์กฐ๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

์—ฐํ•œ์„  → ์•Œ ์ˆ˜ ์—†๋Š” ์ฐธ์กฐ๋ฅผ ์˜๋ฏธํ•œ๋‹ค. (๊ฐ•ํ•œ ์ฐธ์กฐ์ผ ์ˆ˜๋„ ์žˆ๊ณ , ์•ฝํ•œ ์ฐธ์กฐ์ผ ์ˆ˜ ๋„ ์žˆ๋‹ค.)

๊ฐ„๋‹จํ•˜๊ฒŒ ๋ฉ”๋ชจ๋ฆฌ ๊ทธ๋ž˜ํ”„ ๋””๋ฒ„๊ฑฐ์˜ ๊ธฐ๋Šฅ์— ๋Œ€ํ•ด ์•Œ์•„๋ดค๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ๋ˆ„์ˆ˜๋ฅผ ํ™•์ธํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ• ๊นŒ?

ํ…Œ์ŠคํŠธํ•  ๊ธฐ๋Šฅ์— ๋Œ€ํ•ด ์‹คํ–‰ํ•˜๊ณ , ์ด๋ฅผ ์—ฌ๋Ÿฌ๋ฒˆ ๋ฐ˜๋ณตํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์•ฑ์˜ ์Šค๋ƒ…์ƒท์„ ํ™•์ธํ•œ๋‹ค.

  1. ๋ฐ˜๋ณต์ ์œผ๋กœ ๊ธฐ๋Šฅ์„ ํ…Œ์ŠคํŠธํ–ˆ์„๋•Œ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ๋Š˜์–ด๋‚ฌ๋‹ค๋ฉด ๋ˆ„์ˆ˜๋ฅผ ์˜์‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  2. ์ธ์Šคํ„ด์Šค ๊ฐœ์ˆ˜๊ฐ€ ๋งŽ์•„๋„ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ์ง•ํ›„์ผ ์ˆ˜ ์žˆ๋‹ค.
  3. ์™ผ์ชฝ ํŒจ๋„ ๋ฆฌ์ŠคํŠธ์— ํ˜„์žฌ ์•ฑ ์ƒํƒœ์—์„œ ์žˆ์œผ๋ฉด ์•ˆ๋˜๋Š” ๊ฐ์ฒด/ํด๋ž˜์Šค/๋ทฐ ๋“ฑ์ด ํ‘œ์‹œ๋˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.

 

Instruments - Leaks

Instrument๋Š” ์Šค๋ƒ…์ƒท์„ ์ฐ๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ ๋‹ค์ด๋‚˜๋ฏนํ•˜๊ฒŒ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ”„๋กœํŒŒ์ผ๋ง ํ•  ์ˆ˜ ์žˆ๋‹ค. (์‹คํ–‰ํ•ด๋„ ์•ฑ์ด ์ผ์‹œ์ •์ง€ ๋˜์ง€ ์•Š์œผ๋ฉฐ, ์•ฑ์—์„œ ๊ธฐ๋Šฅ์„ ์‹คํ–‰์‹œํ‚ค๋ฉด ๋™์ ์œผ๋กœ ์ธ์Šคํ„ด์Šค๋“ค๊ณผ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ถ”์ ํ•œ๋‹ค)

instrument์—์„œ Leaks๋ฅผ ์‹คํ–‰์‹œํ‚จ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ƒ๋‹จ์— ๋””๋ฒ„๊น…ํ•  Target(์•ฑ)์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋นจ๊ฐ„์ƒ‰ ๋…นํ™”๋ฒ„ํŠผ? ์„ ๋‹ฎ์€ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด Leaks์ด ๋™์ž‘ํ•œ๋‹ค.

๊ฐ์ง€๋œ ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•œ ๋ชฉ๋ก๊ณผ ARC์˜ ๋ ˆํผ๋Ÿฐ์Šค ์นด์šดํŠธ๊นŒ์ง€ ํ‘œ์‹œ๋œ๋‹ค.

ํ•˜๋‹จ ํ•„ํ„ฐ์—์„œ ํ˜„์žฌ ์‹คํ–‰์ค‘์ธ ์•ฑ ์ด๋ฆ„์„ ๊ฒ€์ƒ‰ํ•˜๋ฉด ๊ด€๋ จ์žˆ๋Š” ์ธ์Šคํ„ด์Šค๋“ค์— ๋Œ€ํ•ด์„œ๋งŒ ํŽธํ•˜๊ฒŒ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

Memory Leak Test

https://github.com/Youjunyong/MemoryLeaks.git

 

 

์ฐธ๊ณ ์ž๋ฃŒ

https://www.youtube.com/watch?v=b2AgibUg47k

https://doordash.engineering/2019/05/22/ios-memory-leaks-and-retain-cycle-detection-using-xcodes-memory-graph-debugger/

 

Contents

ํฌ์ŠคํŒ… ์ฃผ์†Œ๋ฅผ ๋ณต์‚ฌํ–ˆ์Šต๋‹ˆ๋‹ค

์ด ๊ธ€์ด ๋„์›€์ด ๋˜์—ˆ๋‹ค๋ฉด ๊ณต๊ฐ ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค.