Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
911 views
in Technique[技术] by (71.8m points)

iphone - SEGV_ACCERR calling [[NSNotificationCenter defaultCenter] removeObserver:self] in dealloc

I'm really at a loss as to how this happened. I have an app that uses ARC. Most of the my view controllers register for NSNotifications. All registrations are done on the main thread.

When a memory warning occurs, the navigation controller used for each non-visible tab is nil'd and is consequently deallocated. In this case, one navigation controller and its view controller were deallocated, and the view controller crashed the app during its dealloc method.

Specifically, it was removing itself from all NSNotificationCenter notifications.

The dealloc method also ran in the main thread, so I don't see how this could be a threading issue.

The crashed line is -[SearchTabViewController dealloc] (SearchTabViewController.m:44)

That line in the code is: [[NSNotificationCenter defaultCenter] removeObserver:self];

The actual crash reason appears to be objc_msgSend referencing a deallocated object.

The problem with that is that there are only 2 messages being sent here, the defaultCenter message to the NSNotificationCenter class (which can never be an invalid reference because it's a class) and the removeObserver: message to the default center object (also can never be deallocated because it's a singleton).

The only other object referenced is self, which can't be deallocated yet because we're still in the "dealloc" method for that object... Basically this crash shouldn't have happened.

Is there something I'm missing here? Relevant part of the crash log below:


Exception Type:  SIGSEGV
Exception Codes: SEGV_ACCERR at 0xe0000008
Crashed Thread:  0

Thread 0 Crashed:
0   libobjc.A.dylib                     0x000035b0 objc_msgSend + 16
1   Anghami Beta                        0x000c7473 -[SearchTabViewController dealloc] (SearchTabViewController.m:44)
2   CoreFoundation                      0x00003311 CFRelease + 101
3   CoreFoundation                      0x0000d95d -[__NSArrayM dealloc] + 141
4   Anghami Beta                        0x0033e73f -[EX2NavigationController .cxx_destruct] (EX2NavigationController.m:51)
5   libobjc.A.dylib                     0x00007f3d object_cxxDestructFromClass(objc_object*, objc_class*) + 57
6   libobjc.A.dylib                     0x000050d3 objc_destructInstance + 35
7   libobjc.A.dylib                     0x000053a7 object_dispose + 15
8   UIKit                               0x000cec89 -[UIViewController dealloc] + 1181
9   CoreFoundation                      0x00003311 CFRelease + 101
10  CoreFoundation                      0x0000da13 -[__NSArrayI dealloc] + 79
11  libobjc.A.dylib                     0x00005489 (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 169
12  CoreFoundation                      0x00005441 _CFAutoreleasePoolPop + 17
13  CoreFoundation                      0x00095f41 __CFRunLoopRun + 1297
14  CoreFoundation                      0x00008ebd CFRunLoopRunSpecific + 357
15  CoreFoundation                      0x00008d49 CFRunLoopRunInMode + 105
16  GraphicsServices                    0x000052eb GSEventRunModal + 75
17  UIKit                               0x00057301 UIApplicationMain + 1121
18  Anghami Beta                        0x0000334d main (main.m:17)
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

So it turned out the crash log was misleading. I was able to eventually get it to happen while connected to the debugger with zombie objects enabled. The actual source of the crash was a loader object that had this controller as it's delegate, tried to call one of the delegate methods after the controller was deallocated.

Now in dealloc, I nil the loader's delegate and cancel the loading if active, and voila no more crashes.


Also, it's worth noting that this crash refused to happen in the simulator, but happened almost every time on the device. So when tracking down weird memory errors, unfortunately the Zombies instrument is not always a viable tool because it requires the app to be run in the simulator.

So the next best thing is to go to Edit Scheme and enable zombie objects there, then build and run on device and wait for it to crash. You don't get the full retain/release history that way, but as in this case, it can give enough information to track down an otherwise elusive problem.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...