|
|
#1 |
|
Unloading NSBundle causing application crash.
Dear All,
I am a developer working on an application developed on Lion using Xcode 4.3.2. One of the modules of the app is to load an NSBundle dynamically and use the same to query some information. I find that when I try to unload the bundle, the application crashes a few seconds later and the calls tack in crash report is as provided below. I believe this type of error happens when user tries to release the same object twice. It tried running the NSZombieEnabled technique along with Xcode but to no avail. Code:
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x000000000396d310
VM Regions Near 0x396d310:
mapped file 000000000395a000-0000000003960000 [ 24K] r--/rwx SM=COW /Applications/########.app/Contents/Resources/information.png
-->
MALLOC metadata 0000000003974000-0000000003975000 [ 4K] r--/rwx SM=ZER
Application Specific Information:
objc[717]: garbage collection is OFF
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 com.apple.CoreFoundation 0x9c120fc1 CFRelease + 49
1 com.apple.CoreFoundation 0x9c1698e6 -[__NSArrayI dealloc] + 246
2 libobjc.A.dylib 0x9367754e _objc_rootRelease + 47
3 libobjc.A.dylib 0x93678c58 (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 404
4 com.apple.CoreFoundation 0x9c14be05 _CFAutoreleasePoolPop + 53
5 com.apple.Foundation 0x95e4476e -[NSAutoreleasePool drain] + 131
6 com.apple.AppKit 0x9c370cbd -[NSApplication run] + 791
7 com.apple.AppKit 0x9c601c59 NSApplicationMain + 1054
8 com.App.MyApp 0x0000323d start + 53
Can you guys also please let me know as to what info you guys can extract from the call stack above? Thanks & Regards. |
|
|
|
0
|
|
|
#2 |
|
The documentation says that before you unload a NSBundle, you must make sure that there are no objects in existence that reference any classes defined by the bundle, since the bundle contains the code for those classes. Since the crash is occurring on the main thread, while draining its autorelease pool, this may be what is happening. Make sure your secondary and tertiary threads can keep track of any such resources and either dispose of them properly or wait until they have been disposed of before unloading the bundle. If this is what is happening, you could consider translating what you get from the bundle into a different class before passing it to the main thread.
__________________
Mr. Paul, sir, I thought you should be advised, there seems to be a zombie tribble clinging to your head, for it is scarfing your brain
Last edited by Sydde; May 8, 2012 at 02:07 AM. |
|
|
|
0
|
|
|
#3 |
|
Hi Sydde,
Thanks for the reply. I am pretty sure that any object that is created is also being released within the bundle before the bundle is unloaded. I have run the Leak test using Instruments tool to plug all the memory leaks that were present in the code. Is it possible that trying to release an object twice could result in such kind of a crash? (though Zombie did not show any such instance). |
|
|
|
0
|
|
|
#4 |
|
Here is what I see: on the main thread, an object named ArrayI is causing the problem when the autorelease pool is drained. Find out how you are handling this object and what it contains, then see what you can do to properly synchronize its lifespan.
If you create an autoreleased object, add it to an array, then release the object, it will be deallocated while it is still in the array when the pool is drained, causing a crash like this when the array is released.
__________________
Mr. Paul, sir, I thought you should be advised, there seems to be a zombie tribble clinging to your head, for it is scarfing your brain
|
|
|
|
0
|
|
|
#5 | |
|
Quote:
|
||
|
|
0
|
|
|
#6 | |
|
Quote:
I would *strongly* recommend never unloading bundles. Just don't do it, it's incredibly difficult to do safely. Specifically, if you ever use a constant NSString (@"foo"), and pass that to any other part of your program, you're pretty much doomed. Calling -copy will not actually create a copy of the string, so even if you try to guard yourself that way, it won't work. When the bundle is unloaded, the binary that the constant string is in goes with it, and anything that uses that string in the future will crash. |
||
|
|
0
|
|
|
#7 | |
|
Quote:
If I were faced with a situation like this and absolutely did have to unload the bundle, I think I might use -performSelectorOnMainThread:withObject:waitUntilDone:YES to make sure everything was properly cleaned up first (in which case, the main thread's method should be autorelease pool bracketed).
__________________
Mr. Paul, sir, I thought you should be advised, there seems to be a zombie tribble clinging to your head, for it is scarfing your brain
|
||
|
|
0
|
|
|
#8 | |
|
Thanks all for providing valuable guidance.
Quote:
In such a scenario, will not calling unload on the bundle (but directly calling release on the bundle object) not cause any kind of an unexpected behaviour (like memory leaks etc) as in my case, the same bundle might needed to be loaded multiple number of times during the same application instance. |
||
|
|
0
|
|
|
#9 | |
|
Quote:
|
||
|
|
0
|
|
|
#10 |
|
The two questions I would have are: are the bundles built by someone else (or might they be), and does the reason for unloading them have something to do with conflicting class definitions? If each bundle, as it should, defines unique classes/subclasses, there really is no need to unload them, they do not take up that much space. And if there is a potential class conflict in code that you have written, you really ought to fix that.
__________________
Mr. Paul, sir, I thought you should be advised, there seems to be a zombie tribble clinging to your head, for it is scarfing your brain
|
|
|
|
0
|
|
|
#11 | |
|
Hi Sydde,
Sorry for the delay in replying. Quote:
Each bundle is giving a different class name. I dont think there is any conflicting class definition. |
||
|
|
0
|
|
|
#12 |
|
After slogging for many days, finally figured out the code that was causing when the unload was called on the bundle.
Code:
//infoDict is an NSDictionary with some objects in it. //line 1 NSArray *arrayKey = [NSArray arrayWithObjects: @"Key1", @"Key2", @"Key3", nil]; //line 2 NSArray *arrayValues = [infoDict objectsForKeys:arrayKey notFoundMarker:@""]; //line 3 NSString *valueOfKey1 = [arrayValues objectAtIndex:0]; From this I could conclude that using an NSArray as illustrated above (atleast for me) in an Bundle was causing an crash. Can you guys from your experience in Cocoa programming figure out as to what is wrong above for it to cause a crash when the bundle was unloaded? |
|
|
|
0
|
|
|
#13 | |
|
Quote:
|
||
|
|
0
|
|
|
#14 | |
|
Quote:
arrayValues clearly must have contained a reference to a constant string that existed within the bundle. The bundle was unloaded before the main thread cycled its runloop, causing the string constant to evaporate as a valid object. Then, when the main thread drained its autorelease pool, it tried to release an invalid object, causing the crash. If you were to bracket the troublesome code with an autorelease pool that was drained at a time when the bundle was certain to still be present, the crash would not happen. Any time you have a crash related to autoreleasing (as indicated by your crash report above), squeezing a pool bracket in around the problem code can help you locate the problem. But making your code cleaner as you have is usually a better choice.
__________________
Mr. Paul, sir, I thought you should be advised, there seems to be a zombie tribble clinging to your head, for it is scarfing your brain
|
||
|
|
0
|
![]() |
|
«
Previous Thread
|
Next Thread
»
| Thread Tools | Search this Thread |
| Display Modes | |
|
|
All times are GMT -5. The time now is 07:23 AM.








Linear Mode
