개발 환경: XCode (6.4), iOS (8.4)

Crash 종류!

먼저, Crash 타입에는 크게 2가지 유형이 있다.

1. SIGABRT ( EXC_CRASH로 불리기도 함)

- Signal Abort, 해당 Signal은 프로그램 스스로 error를 감지하여 abort signal을 보내는 것이다.(This signal indicates an error detected by the program itself and reported by calling abort. )

- C stdlib중에 abort()라는 함수가 있다. 이 함수는 프로그램을 비정상적으로 종료시키는 함수로, 호출한 프로세스에게 SIGABRT를 날려서 프로그램을 종료시킨다. 즉 App이 프로그램 실행 도중 의도치 않은 동작을 감지 했을때 abort()를 호출하여 App을 종료시키는 것이다. 

- 이 경우는 Crash 원인을 찾기에 비교적 쉬운 타입에 속한다. 왜냐하면 App(프로그램)이 Crash 원인을 알고 있어서 Debug Output에 Crash 원인을 출력해주기 때문이다.


2. EXC_BAD_ACCESS( SIGBUS, SIGSEGV )

- SIGSEGV : signal segmentation violation, 할당된 메모리의 범위를 벗어나는곳에서 읽거나 쓰기를 시도할 때 발생됨.(프로그램 자신의 영역이 아닌 다른 영역의 메모리를 접근했을 때) 또는 readonly 메모리에 대하여 write를 시도했을때 발생되는 error signal 이다.

- SIGBUS : signal bus, SIGSEGV와 같이 메모리에 비정상적인 접근을 할 때 발생하는데, SIGSEGV는 valid한 메모리에 비 정상적인 접근을 할 때 발생하며, SIGBUS는 invalid한 메모리에 접근할 때 발생한다.

- 이 경우는 Crash 원인을 찾기가 어렵다. App(프로그램)이 Crash원인을 감지하고 App을 중단 시킨것이 아니기 떄문에 Debug Output에 Crash원인을 출력하지 않는다.

다행인점은, XCode가 업그레이드 되면서 EXC_BAD_ACCESS Crash가 일어나야 되는 상황도 미리 감지하여 SIGABRT Crash를 발생시키는 것으로 보인다. 실제로 old 버젼 XCode에서 EXC_BAD_ACCESS Crash가 일어나던 것이 최신 버젼에서는 SIGABRT Crash를 발생시키는 사례를 종종 볼 수 있다.

Crash 대처법

- 위에서 소개한 SIGABRT, EXC_BADACCESS Crash 둘다 XCode가 업데이트 되면서 왠만한 Crash들은 해당 code line 위치에서 break point가 걸린다. 하지만 그렇지 않은경우 해당 crash를 해결하기 위한 기본적인 팁을 소개하겠다.

1. SIGABRT

- 위 Crash는 SIGABRT 타입이기 때문에  debug output에 Exeption Reason이 출력된다. 하지만 해당 Exeption이 일어난 위치를 확인하고 싶을때는 All Exception BreakPoint를 설정해 준다.


- 왼쪽 Navigator에서 BreakPoint Navigator를 활성화 시킨다. 


- 왼쪽 하단에 '+' 버튼을 눌러 모든 Exception에 Breakpoint를 지정한다.


이제 SIGABRT Crash가 발생되기 직전 exception이 발생된 코드 라인에 break point가 걸려 있을것이다. 해당 기능을 사용하면 좀 더 빠른시간안에 crash원인을 찾을 수 있다.

2. EXC_BAD_ACCESS

- EXC_BAD_ACCESS Crash의 대부분의 원인은 release retain 메커니즘 오류이다. 보통 MRC 모드에서 많이 발생되나, ARC 모드에서도 간혹 발생된다.

- 위 스샷 처럼 Crash가 난 위치에서 break point가 잡히지 않았을때는 Zombie Objects를 이용한다.


- 메뉴 Product -> Scheme -> Edit Scheme 에서 Enable Zombie Objects를 활성화 한다.

- Zombie Objects가 하는 일은 메모리에 할당된 객체가 release될때 dealloc 시키지 않고 모니터링 하는 것이다. 해당 객체를 모니터링 하는 도중 프로그램이 객체에 접근하면 에러 메시지를 날려 어떤 객체에 invalid한 메모리 접근이 일어났는지 알려주는 것이다.


* 요약: main 함수에서 SIGABRT Crash가 발생되면 All Exception Break Point를 지정하고 다시 실행해서 정확한 Crash 위치를 확인해라, EXC_BAD_ACCESS Crash가 발생되면 Zombie Objects를 활성화 시켜 어느 객체에서 메모리 접근 오류가 발생했는지 확인해라.

* http://stackoverflow.com/questions/3327828/xcode-lldb-how-to-get-information-about-an-exception-that-was-just-thrown (exception print)



'IOS > 공통' 카테고리의 다른 글

About Bundle  (0) 2017.02.14
iOS Architecture  (0) 2016.12.18
UIApplicationMain?  (0) 2016.02.18
[iOS 9] Search  (0) 2015.11.05
[IOS 9] 개요  (0) 2015.11.05
Posted by 홍성곤
,