SEGV_ACCERR calls [[NSNotificationCenter defaultCenter] removeObserver: self] in dealloc

I really don't understand how this happened. I have an application that uses ARC. Most controllers of my kind are registered for NSNotifications. All registrations are performed on the main thread.

When a memory warning occurs, the navigation controller used for each invisible tab is nil'd and therefore freed. In this case, one navigation manager and its kind controller were freed, and the view controller crashed the application during its dealloc method.

In particular, it was removed from all NSNotificationCenter notifications.

The dealloc method also runs in the main thread, so I don’t see how this could be a problem with threads.

The -[SearchTabViewController dealloc] (SearchTabViewController.m:44) string -[SearchTabViewController dealloc] (SearchTabViewController.m:44)

This line in code: [[NSNotificationCenter defaultCenter] removeObserver:self];

The actual cause of the failure looks like objc_msgSend referring to the freed object.

The problem is that only 2 messages are sent here, the defaultCenter message to the defaultCenter class (which can never be an invalid reference because it is a class) and the removeObserver: message removeObserver: default center object (also can never be freed because it is solitary).

The only other referenced object is self, which cannot yet be freed due to the fact that we are still in the dealloc method for this object ... Basically this failure should not happen.

Is there something I am missing here? The relevant part of the crash log is 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) 
+1
source share
1 answer

So, it turned out that the crash log is misleading. I was able to eventually make it happen when connected to a debugger with zombie objects turned on. The actual source of the failure was the loader object that this controller had when it delegated, tried to call one of the delegate methods after the controller was released.

Now in dealloc I will lose the bootloader delegate and cancel the boot if it is active and voila will no longer work.


In addition, it is worth noting that this accident was refused in the simulator, but this happened almost every time on the device. Therefore, when you find strange memory errors, unfortunately, the Zombies tool is not always a viable tool because it requires the application to run in the simulator.

So, it's best to go to the Edit Scheme and turn on zombie objects there, and then build and run on the device and wait for it to fail. You will not receive a complete save / release history in this way, but, as in this case, it can provide enough information to track an elusive problem.

+3
source

All Articles