My app did't crashed.
DDXMLDocument *d = [[DDXMLDocument alloc] initWithData:abookConnData options:0 error:nil];
books = [d nodesForXPath:#"abooks/abook" error:nil];
I changed object of DDXMLDocument to autorelease and my app began crashed. But Why?
DDXMLDocument *d = [[[DDXMLDocument alloc] initWithData:abookConnData options:0 error:nil] autorelease];
books = [d nodesForXPath:#"abooks/abook" error:nil];
My app crashed in the DDXMLNode.
[DDXMLNode XMLStringWithOptions:]
You don't give enough code to say for sure, but this is almost certainly a case where your DDXMLDOcument* (d) is being released before you use it.
Try turning on Zombie detection and also put a breakpoint on Exception. Often, that can lead you to the exact line of code where the problem is.
Another trick for debugging is to create a subclass of DDXMLDocument and override ALLOC and RELEASE to call NSLog() the event (then [super alloc] or [super release]!) so you can watch what's happening.
Related
I have an app that works fine on the simulator 6.1, works fine on the iPhone5 and iPad3 on iOS6.1 but when run on iPhone4S it crashes in this method with Exc Bad Access:
-(void)parsePlistIntoCD{
self.managedObjectContext = [[SDCoreDataController sharedInstance] backgroundManagedObjectContext];
// 3: Now put the plistDictionary into CD...create get ManagedObjectContext
NSManagedObjectContext *context = self.managedObjectContext;
NSError *error;
//Create Request & set Entity for request
NSFetchRequest *holidayRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *topicEntityDescription = [NSEntityDescription entityForName:#"Holiday" inManagedObjectContext:context];
[holidayRequest setEntity:topicEntityDescription];
//Create new NSManagedObject
//Holiday *holidayObjectToSeed = nil;
Holiday *newHoliday = nil;
//Execute fetch just to make sure?
NSArray *holidayFetchedArray = [context executeFetchRequest:holidayRequest error:&error];
**if (error) NSLog(#"Error encountered in executing topic fetch request: %#", error); // if I comment this line out it reaches as far as the next bold line**
// No holidays in database so we proceed to populate the database
if ([holidayFetchedArray count] == 0) {
//Get path to plist file
NSString *holidaysPath = [[NSBundle mainBundle] pathForResource:#"PreloadedFarsiman" ofType:#"plist"];
//Put data into an array (with dictionaries in it)
NSArray *holidayDataArray = [[NSArray alloc] initWithContentsOfFile:holidaysPath];
**NSLog(#"holidayDataArray is %#", holidayDataArray);**
//Get number of items in that array
int numberOfTopics = [holidayDataArray count];
//Loop thru array items...
for (int i = 0; i<numberOfTopics; i++) {
//get each dict at each node
NSDictionary *holidayDataDictionary = [holidayDataArray objectAtIndex:i];
//Insert new object
newHoliday = [NSEntityDescription insertNewObjectForEntityForName:#"Holiday" inManagedObjectContext:context];
//Parse all keys in each dict object
[newHoliday setValuesForKeysWithDictionary:holidayDataDictionary];
//Save and or log error
[context save:&error];
if (error) NSLog(#"Error encountered in saving topic entity, %d, %#, Hint: check that the structure of the pList matches Core Data: %#",i, newHoliday, error);
};
}
//set bool that specifies the coredata has been populated from plist already
NSString *bundleVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
NSString *appFirstStartOfVersionKey = [NSString stringWithFormat:#"first_start_%#", bundleVersion];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:#(YES) forKey:appFirstStartOfVersionKey];
[prefs synchronize];
}
Why only on 4S? It gives no console log and the last know method traversed in this one above. Here is a pic:
And as mentioned above, if I uncomment that NSLog line it reaches as far as logging the array, as shown in the pic. If I leave it in it stops at that line.
NSArray *holidayFetchedArray = [context executeFetchRequest:holidayRequest error:&error];
if (error)
NSLog(#"Error encountered in executing topic fetch request: %#", error);
No no no no no. I know this is a difficult pattern, but please let's try to do it right. Not if (error). error could be anything (esp. under non-ARC). The test is if (!holidayFetchedArray).
For all of these methods that return a value and also take an NSError** by indirection, you test the result to see if it is nil. If it is, then there was an error because returning nil is the sign that there was an error. Then and only then you may touch the error meaningfully.
The docs are always quite clear about this, though it is true that a fog can come over one's eyes at the critical instance, so I've added some comments in italic brackets to call out the key points:
request
A fetch request that specifies the search criteria for the
fetch.
error
If there is a problem executing the fetch, upon return
contains an instance of NSError that describes the problem.
[And if there is no problem executing the fetch, contains garbage so don't touch it!]
Return Value
An array of objects that meet the criteria specified by request
fetched from the receiver and from the persistent stores associated
with the receiver’s persistent store coordinator. If an error occurs,
returns nil. [And that, forsooth, is the sign that an error did occur.] If no objects match the criteria specified by request,
returns an empty array.
This might be the cause of your trouble or it might not, but you must fix it now. I want you to go through all your code looking for NSError* variables declared for use in this pattern and fix all of them! Thank you. Here endeth the lesson.
This is a stab in the dark b/c you haven't identified the line of code where the crash occurs. I recommended you set a breakpoint and then step through until you hit the crash. If what I say below doesn't resolve the issue then edit your post and add more info about where the crash occurs and we'll go from there.
Here's something to check. The line:
[newHoliday setValuesForKeysWithDictionary:holidayDataDictionary]
may be crashing if any of the keys in holidayDataDictionary aren't valid for an instance of the Holiday class.
With regard to your question about why it only crashes on your iPhone 4S there's not enough data to explain that yet. Depending on how you've been doing testing and core data migration (if at all) you may have a model inconsistency on that device, though I don't see anything in the screen shot you posted pointing me in that direction. I would try uninstalling/reinstalling your app and see if the crash is still iPhone 4S only.
I have run the leaks in Instruments and it is showing me a memory leak with a 100% value. I am able to see the line of code that is causing the problem. But not really sure what the error is..
- (void) listAllBooks {
if (marrListFromDB != nil) {
[marrListFromDB removeAllObjects];
marrListFromDB = nil;
}
marrListFromDB = [[NSMutableArray alloc] init];
ServerCommunicationAPI *servApi = [[ServerCommunicationAPI alloc] init];
servApi.delegate = self;
NSURL *url = [NSURL URLWithString:kLISTCONTENTS];
[servApi listBooksWithDeviceID:singleton.g_strdevID deviceKey:singleton.g_strdevID andSessionString:singleton.g_strSessionID sessionKey:#"sessionKey" URL:url andRequestMethod:#"POST"];
}
The line of error is the last one. Not sure why it is causing a memory leak... Need some guidance..
It is hard to tell from the information provided, but maybe the delegate property of ServerCommunicationAPI is declared as (strong)? In this case servApi could never be released, because it keeps a strong reference to itself (retain cycle).
I suggest that you check in instruments which kind of object leaks, this would make the answer much easier.
Try out this. May it resolve your memory leak problem.
- (void) listAllBooks {
if (marrListFromDB != nil) {
[marrListFromDB removeAllObjects];
marrListFromDB = nil;
}
ServerCommunicationAPI *servApi ;
marrListFromDB = [[NSMutableArray alloc] init];
if(servApi == nil){
ServerCommunicationAPI *servApi = [[ServerCommunicationAPI alloc] init];
}//Every time it going to alloc. It's strong object may be due do this memory leak happens.
servApi.delegate = self;
NSURL *url = [NSURL URLWithString:kLISTCONTENTS];
[servApi listBooksWithDeviceID:singleton.g_strdevID deviceKey:singleton.g_strdevID andSessionString:singleton.g_strSessionID sessionKey:#"sessionKey" URL:url andRequestMethod:#"POST"];
}
Just another idea: Maybe you execute your code in a separate thread for which no autorelease pool has been set up? In this case the message sent to servApi could create autorelease objects that cannot be released later since no autorelease pool exists.
So, if your code is not executed in the main thread, please check if an autorelease pool has been set up using a #autoreleasepool {...} block for your thread.
i am getting this error and dont know what to do with that:
AppName(3786,0xa0810540) malloc: *** mmap(size=16777216) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
If i set a breakpoint to that line that occurs the error, i dont know what i have to search specially for. In instruments i have checked the allocations and the value is increasing until 14,5 GB of all allocations.
Can someone give me help?
brush51
EDIT 1:
More informations:
- I am trying this in the simulator, not on the iOS device.
- Thats all of the output(i am getting this error more times).
- the error occurs on this line:
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest *fetchREntitySetsCards = [[[NSFetchRequest alloc] init] autorelease];
//NSFetchRequest *fetchREntityRelCardsAnswersNotes = [[[NSFetchRequest alloc] init] autorelease];
NSEntityDescription *entitySetsCards = [NSEntityDescription entityForName:#"EntitySetsCards" inManagedObjectContext:context];
//NSEntityDescription *entityRelCardsAnswersNotes = [NSEntityDescription entityForName:#"EntityRelCardsAnswersNotes" inManagedObjectContext:context];
setEntity:entityCard];
[fetchREntitySetsCards setEntity:entitySetsCards];
//[fetchREntityRelCardsAnswersNotes setEntity:entityRelCardsAnswersNotes];
NSArray *fetchedObjSetsCards = [context executeFetchRequest:fetchREntitySetsCards error:&error];
//The error is here--->
//NSArray *fetchedObjRelCardsAnswersNotes = [context executeFetchRequest:fetchREntityRelCardsAnswersNotes error:&error];
//Badges für TabBarItem Inbox setzen
setsCount = [context countForFetchRequest:fetchREntityUserSet error: &error];
cardsCount = [context countForFetchRequest:fetchREntityCard error: &error];
Sounds strange, but I had the same behavior when main thread was overloaded.
Memory usage was optimal enough: instruments shows no leaks and live memory was about 2Mb, no memory warnings while running on a device, all massive allocation was done inside autorelease pools etc.
But there was very huge process of storing data to db (using Core Data) made on main thread. Just moving the storing code to background process like this
dispatch_async(dispatch_get_global_queue
(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
BOOL result = NO;
result = [[DataManager sharedInstance] storeGuestsToDB];
dispatch_async(dispatch_get_main_queue(), ^{
//finalization
}
}
fixed my problem.
Googling will reveal quite a few tutorials on using instruments to understand what is going on with your memory:
How to debug memory leaks: (tutorial)
http://www.raywenderlich.com/2696/how-to-debug-memory-leaks-with-xcode-and-instruments-tutorial
And another:
Finding Obj-C memory leaks (video)
http://www.youtube.com/watch?v=R449qEuexNs&feature=related
*There are many similar questions on stackoverflow you might benefit from.
I had this issue due to a recursive call in a view controller's viewWillLayoutSubviews. I was invalidating the layout of a collection view causing an endless cycle of repeatedly laying out views.
I am getting a list of errors like the following error when I compile my project for iOS.
2011-08-25 12:32:44.016 rtsp[55457:6003]
*** __NSAutoreleaseNoPool(): Object 0x64095a0 of class __NSArrayM
autoreleased with no pool in place - just leaking
It appears because of the following function
- (void) start {
//Existing code
session = [[RTSPClientSession alloc] initWithURL:
[NSURL URLWithString:
#"rtsp://video3.americafree.tv/AFTVComedyH2641000.sdp"]];
[session setup];
NSLog(#"getSDP: --> %#",[ session getSDP ]);
NSArray *array = [session getSubsessions];
for (int i=0; i < [array count]; i++) {
RTSPSubsession *subsession = [array objectAtIndex:i];
[session setupSubsession:subsession clientPortNum:0 ];
subsession.delegate=self;
[subsession increaseReceiveBufferTo:2000000];
NSLog(#"%#", [subsession getProtocolName]);
NSLog(#"%#", [subsession getCodecName]);
NSLog(#"%#", [subsession getMediumName]);
NSLog(#"%d", [subsession getSDP_VideoHeight]);
NSLog(#"%d", [subsession getServerPortNum]);
}
[session play];
NSLog(#"error: --> %#",[session getLastErrorString]);
[session runEventLoop:rawsdp];
}
When I add and NSAutoreleasePool to my function
- (void) start {
NSAutoReleasePool *pool=[[NSAutoReleasePool alloc] init];
session = [[RTSPClientSession alloc] initWithURL:[NSURL ...
...
[pool drain];
}
The error is gone but I don't get any output from my function. Is adding NSAutoreleasePool the right solution?
You get the message on the console because you are running the start method on a background thread and have not placed an Autorelease pool in place that will take care of reclaiming objects once they have been released (release count == 0 ),this doesnt happen in the main thread because the main thread already has a pool in place, for background threads u spawn you are responsible to set up the autorelease pool... your solution is the right solution to the problem.. so here is an example of when to and where to use autorelease pool
One way to spawn something to execute in the background is by calling performSelectorInBackground method of NSObject which i assume you are doing
[myObject performSelectorInBackground:(#selector(myBackgroundMethod:) withObject:nil];
Now this method is going to execute on a background thread and you need to place an Autorelease pool in place in order for it not to leak, like so
-(void)myBackgroundMethod:(id)sender
{
NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init];
//do stuff
[pool release];
}
hope that clears it up
Daniel
I detach a thread calling my method which has a while-loop. Even though I have them marked as autoreleasepool, I release the objects manually, since the while-loop can continue on for a some time.
The problem is that after a while, the app crashes due to memory problems. If I look in Instruments, I can see a huge pile of NSStrings allocated and a stairway to heaven is created in the graph. What have I failed to release?
while (keepGettingScores)
{
NSString *jsonString = [[NSString alloc] initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
NSDictionary *json = [jsonString JSONValue];
[jsonString release];
NSMutableArray *scores = [[NSMutableArray alloc] init];
[scores setArray:(NSMutableArray*)[[jsonString JSONValue] objectForKey:#"scores"]];
NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:#"totalScore" ascending:NO];
[scores sortUsingDescriptors:[NSArray arrayWithObject:sorter]];
[sorter release];
[self performSelectorOnMainThread:#selector(updatePlayerTable:) withObject:scores waitUntilDone:NO];
[scores release];
[NSThread sleepForTimeInterval:1.0];
}
I don't see anything glaring, could there be an issue under the hood in your JSON library?
Are you draining your pool after your thread is finished executing?
You need to create an NSAutoreleasePool and call its drain method when your thread is finished executing.
In one of my projects, I had a thread that needed to create a lot of autorelease objects and found it useful to periodically drain the pool as the thread was running.
- (void)doStuff:(NSObject *)parent {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
/* Do lots of stuff *.
/* Periodically, I'd drain and recreate the pool */
[pool drain];
pool = [[NSAutoreleasePool alloc] init];
/* The rest of my stuff */
[pool drain];
}
And doStuff: is called using detachNewThreadSelector:
ok some BIG problems i see is
1
this..
[self performSelectorOnMainThread:#selector(updatePlayerTable:) withObject:scores waitUntilDone:NO];
is passing scores which could be getting retained by something else and that would also retain all the objects it contains.
2
scores is a nsmutablearray and is explicitly defined as NOT THREAD SAFE yet you are passing it across threads.
3
those [blah JSONvalue] things should be autoreleased and that is not apple api, apple has no public JSON api for iphone. that is most likely SBJSON library which puts categories on apple classes(nsstring, nsarray, nsdictionary, etc) for convenient JSON parsing.