iOS 문제 해결

9028 단어
iOS 버전의 품질을 담당하는 동안 많은 난제와 붕괴에 부딪혔다. 그들의 통일된 특징은 붕괴 창고 정보가 매우 명확하지 않아 해결하기가 매우 어렵다는 것이다.대머리가 되었던 붕괴들을 정리하고 기록해 보세요.(부정기적으로 업데이트됨)
1. 멀티스레드 운영 NSMutable 유형 데이터
1. NSMutable Data appendBytes 충돌
5 Foundation    __NSMutableDataGrowBytes + 272
6 Foundation    -[NSConcreteMutableData appendBytes:length:] + 372
7 Foundation    ___49-[_NSDispatchData enumerateByteRangesUsingBlock:]_block_invoke + 44
8 libdispatch.dylib __dispatch_data_apply + 128
9 libdispatch.dylib dispatch_data_apply + 40
10 Foundation   -[_NSDispatchData enumerateByteRangesUsingBlock:] + 64
11 Foundation   -[NSConcreteMutableData appendData:]

2、BlocksKit 하위 스레드로 이동NSMutable Dictionary 붕괴
0 libobjc.A.dylib   objc_retain + 8
1 MojiWeather   __35-[NSDictionary(BlocksKit) bk_each:]_block_invoke (NSDictionary+BlocksKit.m:14)
2 CoreFoundation    -[__NSDictionaryM enumerateKeysAndObjectsWithOptions:usingBlock:] + 232
3 MojiWeather   -[NSDictionary(BlocksKit) bk_each:] (NSDictionary+BlocksKit.m:17)
4 MojiWeather   -[AdvSystemNetworkManager p_handleNoAdResponse:] (AdvSystemNetworkManager.m:394)
5 MojiWeather   __33-[GCDAsyncSocket closeWithError:]_block_invoke (GCDAsyncSocket.m:3143)
6 libdispatch.dylib __dispatch_call_block_and_release + 24
7 libdispatch.dylib __dispatch_client_callout + 16
8 libdispatch.dylib __dispatch_queue_serial_drain$VARIANT$mp + 528
9 libdispatch.dylib __dispatch_queue_invoke$VARIANT$mp + 340
10 libdispatch.dylib    __dispatch_root_queue_drain_deferred_wlh$VARIANT$mp + 404
11 libdispatch.dylib    __dispatch_workloop_worker_thread$VARIANT$mp + 644
12 libsystem_pthread.dylib  _pthread_wqthread + 932

이러한 충돌의 공통점은 매우 뚜렷하다. 1. 충돌 창고에 NSMutable이 접두사라는 클래스 대상이 나타났다.2. 충돌 창고는 모두 하위 라인에서 호출됩니다.
장면을 트리거하려면 다음과 같이 하십시오.
여러 스레드가 동시에 NSMutable Data, NSMutable Array를 조작하면 충돌이 발생하기 쉽다.
솔루션:
1. 직렬 대기열에서 조작한다.
//          
dispatch_async(serialQueue, ^{
    //critical section,          。
});

2. 자물쇠를 채운다.
//       
dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
//critical section,          。
dispatch_semaphore_signal(self.semaphore);


참고:
애플 공식 빗질 라인 불안정 클래스
2, CTTelephony NetworkInfo 충돌
0 libobjc.A.dylib   objc_msgSend + 16
1 CoreTelephony _ServerConnectionCallback(__CTServerConnection*, __CFString const*, __CFDictionary const*, void*) + 52
2 CoreTelephony invocation function for block in CTServerState::sendNotification_sync(CTEvent, __CFString const*, __CFDictionary const*) const + 32
3 libdispatch.dylib __dispatch_call_block_and_release + 24
4 libdispatch.dylib __dispatch_client_callout + 16
5 libdispatch.dylib __dispatch_queue_drain + 1216
6 libdispatch.dylib __dispatch_queue_invoke + 132
7 libdispatch.dylib __dispatch_root_queue_drain + 664
8 libdispatch.dylib __dispatch_worker_thread3 + 108
9 libsystem_pthread.dylib   _pthread_wqthread + 816


이 충돌은 iOS9 및 다음 시스템 버전에서만 발생합니다.언뜻 보기에는 이해하기 어렵지만 붕괴 창고에 코어텔레포니라는 라이브러리가 있는 것을 자세히 보면 알 수 있다. iOS9 이하 버전의 CT텔레포니 Network Info 대상에 버그가 있고 이미 풀린 CT텔레포니 Network Info 대상은 알림을 받고 붕괴된다.프로젝트를 계속 살펴보면 구 버전인 Reachability의 CTTTelephony NetworkInfo가 클래스 변수가 아니라 여러 번 초기화되고 방출되어 붕괴 위험이 있음을 발견할 수 있습니다.
장면 트리거
이전 버전의 [Reachability reachability ForLocal WiFi] isReachable ViaWiFi] 등의 방법을 여러 곳에서 호출합니다.
솔루션
CTTelephony Network Info를 클래스 변수로 수정하거나 AFN의 AFNetworkReachability Manager를 대체합니다.
비고
CTTelephonyNetworkInfo should not be released
3. 메모리 유출 붕괴
0 libobjc.A.dylib   objc_object::release() + 16
1 libobjc.A.dylib   (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 844
2 libobjc.A.dylib   (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 844
3 libdispatch.dylib __dispatch_last_resort_autorelease_pool_pop + 36
4 libdispatch.dylib __dispatch_root_queue_drain + 1308
5 libdispatch.dylib __dispatch_worker_thread3 + 120
6 libsystem_pthread.dylib   _pthread_wqthread + 1176


호출 창고 AutoreleasePoolPage:::pop을 통해 시스템이 자동 방출 탱크의 방출 작업을 호출하고 있음을 알 수 있습니다(objc object::release ()를 통해 대상 메모리가 방출될 때 발생하는 충돌임을 알 수 있습니다). 따라서 메모리 유출 문제로 판정됩니다.
장면 트리거
instrument 분석을 통해 다음 코드에 심각한 메모리 유출 문제가 있음을 알 수 있습니다.
MTLModel.m line 45: [obj validateValue:&validatedValue forKey:key error:error]

솔루션
링크를 참조하여 MTLModel에 분류 방법을 추가합니다.
https://github.com/Mantle/Mantle/issues/818
https://github.com/Mantle/Mantle/issues/787#issuecomment-286608719
비고
메모리 유출과 같은 문제의 항목에 따라 원인이 다르므로 instrument의leaks 검사를 많이 사용하고 붕괴 추세를 통해 문제가 발생한 업무 모듈을 대체적으로 확인하는 것을 권장합니다.
4. 백그라운드 작업 UIWindow 문제
0 libobjc.A.dylib   objc_retain + 16
1 UIKit ___39-[UIWindow _noteOverlayInsetsDidChange]_block_invoke + 132
2 UIKit __runAfterCACommitDeferredBlocks + 292
3 UIKit __cleanUpAfterCAFlushAndRunDeferredBlocks + 560
4 UIKit __afterCACommitHandler + 168
5 CoreFoundation    ___CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 32
6 CoreFoundation    ___CFRunLoopDoObservers + 372
7 CoreFoundation    ___CFRunLoopRun + 1024
8 CoreFoundation    CFRunLoopRunSpecific + 444
9 GraphicsServices  GSEventRunModal + 180
10 UIKit    -[UIApplication _run] + 684
11 UIKit    UIApplicationMain + 208
12 MojiWeather  main (main.m:16)
13 libdyld.dylib    _start + 4

iOS10 이하 장치에만 표시됩니다.붕괴 창고는 유용한 정보를 전혀 얻지 못하지만 Bugly가 올린 페이지 추적 데이터에서 매번 붕괴된 페이지가 앱을 시작할 때 2단계 Splash에서 전시될 때 붕괴된 것을 알 수 있다. 우리 프로젝트의 2단계 Splash는 RootViewController를 설정하는 방식으로 전시된 것이기 때문에 기본적으로 Splash의 Window를 조작할 때 발생하는 붕괴라고 판단한다.계속해서 로그를 조사한 결과 거의 모든 붕괴 사용자가 응용 프로그램:didFinish Launching With Options: 방법 중의launch Option의 키 값은 UIAPplication Launch Options Location Key이기 때문에 이 붕괴는 사용자 백엔드 위치가 바뀌었을 때 사용자가 백엔드 조작에서 발생한 것이 아니라고 판단했다.
장면 트리거
백그라운드 로케이션 기능이 트리거될 때 UIWindow 작업을 적용하면
솔루션
응용 프로그램:didFinish Launching With Options:에서 launch Option을 판단합니다. UIAPplication Launch Options Location Key 방식으로 응용에 들어가면 2급 Splash 전시를 터치하지 않습니다.UIWindow가 작동하지 않습니다.
5. 백그라운드 OpenGL 그리기 문제
프로젝트가cocos2d-objc에 접속되었기 때문에 육륙에서 계속해서 각종 백그라운드 그리기 문제가 발생한 적이 있다.붕괴 창고에 GLEngine, OpenGLES, gpusSubmitDataBuffers 등과 관련된 글자가 나타나면 그림 그리기에 문제가 있다고 확신할 수 있다.
장면 트리거
이곳의 장면은 두 가지가 있다. 첫째, 같은 문제4,launchOption이UIApplicationLaunchOptionsLocationKey일 때 응용 프로그램은 백엔드에 있는데 이때 OpenGL을 터치하면 붕괴된다.
2. 사용자가 수동으로 백그라운드에 들어간 후(UIAPplication DidEnterBackground 호출) 그림이 멈추지 않습니다.
솔루션
1. 백그라운드 포지셔닝을 터치하여 인용에 들어갈 때 프로그램은willFinishLaunchingWithOptions와didFinishLaunchingWithOptions를 걷지만 didBecomeActive를 걷지 않기 때문에didBecomeActive 방법에 표지 위치를 추가할 수 있고didBecomeActive를 통과하지 않았을 때cocos2D의 그리기를 터치하지 않습니다.
2. didEnterBackground에서 드로잉을 중지하는 작업을 추가합니다.
비고
OpenGL ES May Not Be Used in Background Apps
6.Testflight 패키지 붕괴 문제.
테스트는 Testflight 패키지를 사용하여 Debug 패키지를 덮어씁니다. 붕괴가 자주 발생하지만, 개발은 xcode Debug를 사용하여 붕괴를 다시 나타낼 수 없습니다.장치 충돌 로그 내보내기 충돌 스택 정보는 다음과 같습니다.
Application Specific Information:
abort() called

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0:
0   libsystem_kernel.dylib          0x000000021b8619fc __ulock_wait + 8
1   libdispatch.dylib               0x000000010c42d878 0x10c428000 + 22648
2   libdispatch.dylib               0x000000010c42d9b0 0x10c428000 + 22960
3   libdispatch.dylib               0x000000010c43bbb8 0x10c428000 + 80824
4   libdispatch.dylib               0x000000010c43b5d0 0x10c428000 + 79312
5   GPUToolsCore                    0x000000010c4bc488 0x10c4ac000 + 66696
6   GPUToolsCore                    0x000000010c4bf204 0x10c4ac000 + 78340
7   dyld                            0x0000000109235504 ImageLoaderMachO::doModInitFunctions+ 103684 (ImageLoader::LinkContext const&) + 404
8   dyld                            0x0000000109235738 ImageLoaderMachO::doInitialization+ 104248 (ImageLoader::LinkContext const&) + 36
9   dyld                            0x0000000109230768 ImageLoader::recursiveInitialization+ 83816 (ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 464
10  dyld                            0x000000010922f798 ImageLoader::processInitializers+ 79768 (ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 136
11  dyld                            0x000000010922f854 ImageLoader::runInitializers+ 79956 (ImageLoader::LinkContext const&, ImageLoader::InitializerTimingList&) + 84
12  dyld                            0x000000010921e680 dyld::initializeMainExecutable+ 9856 () + 184
13  dyld                            0x0000000109223468 dyld::_main+ 29800 (macho_header const*, unsigned long, int, char const**, char const**, char const**, unsigned long*) + 4600
14  dyld                            0x000000010921d044 _dyld_start + 68


솔루션
패키지를 제거하고 테스트를 위해 TestFlight 패키지를 다시 설치합니다.
비고
https://forums.xamarin.com/discussion/103272/crash-ios-11-version-on-ios-10-exc-crash-abort-called-in-ad-hoc

좋은 웹페이지 즐겨찾기