I am getting memory leaks in Instruments in the following Sqlite Code.
NSArray *result = [self executeQuery:sql arguments:argsArray];
It calls following method.
- (NSArray *)executeQuery:(NSString *)sql arguments:(NSArray *)args {
sqlite3_stmt *sqlStmt;
if (![self prepareSql:sql inStatament:(&sqlStmt)])
return nil;
int i = 0;
int queryParamCount = sqlite3_bind_parameter_count(sqlStmt);
while (i++ < queryParamCount)
[self bindObject:[args objectAtIndex:(i - 1)] toColumn:i inStatament:sqlStmt];
NSMutableArray *arrayList = [[NSMutableArray alloc] init];
int columnCount = sqlite3_column_count(sqlStmt);
while ([self hasData:sqlStmt]) {
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
for (i = 0; i < columnCount; ++i) {
id columnName = [self columnName:sqlStmt columnIndex:i];
id columnData = [self columnData:sqlStmt columnIndex:i];
[dictionary setObject:columnData forKey:columnName];
}
[arrayList addObject:[dictionary autorelease]];
}
sqlite3_finalize(sqlStmt);
return arrayList;
}
How do I solve it ?
We'd need to see the code of your executeQuery method - it should be returning an auto-released result, but perhaps it isn't.
You could try ;
NSArray *result = [[self executeQuery:sql arguments:argsArray] autorelease];
But I'd be wary of just blindly trying that without actually seeing what executeQuery does in detail.
EDIT:
OK, here's your problem;
NSMutableArray *arrayList = [[NSMutableArray alloc] init];
Either create it as an auto-released array, or finish the method with;
return [arrayList autorelease];
Related
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I get this message "Tread 9: EXC_BAD_ACCESS (code=1, address=0x70000010) in this method (but this bug is being created only when in another thread file is being downloaded ):
- (NSMutableDictionary *) getDictionaryAllStatin:(sqlite3*)database
{
if (self._streetsArrey == nil || self._streetsArrey.count <= 0) {
[self getArrayAllStatin:database];
}
/*--------------------------------------------------------------*/
NSMutableDictionary *result1 = [[NSMutableDictionary alloc] init];
for (StreetData *street in _streetsArrey) {
NSString * name = [self deleteContractionWithText:street._name];
NSArray * arr = [name componentsSeparatedByString:#" "];
NSMutableArray *arrm = [[NSMutableArray alloc] initWithArray:arr];
arr = nil;
[arrm addObject:name];
for (NSString *txt in arrm) {
int lengthText = txt.length;
for (int i = 2 ; i <= lengthText; i++) {
NSString * key = [txt substringToIndex:i];
key = [key lowercaseString];
NSMutableDictionary *isSet = [result1 objectForKey:[NSNumber numberWithInt:[key hash]]];
if (isSet == nil) {
isSet = [[NSMutableDictionary alloc]init];
}
[isSet setObject:street forKey:[NSNumber numberWithInt:street._streetId]];
[result1 setObject:isSet forKey:[NSNumber numberWithInt:[key hash]]];
isSet = nil;
key = nil;
}
}
}
NSMutableDictionary *result = [[NSMutableDictionary alloc] init];
for (id key in result1) {
NSMutableDictionary *dictionary = [result1 objectForKey:key];
NSArray *arr = [dictionary allValues];
[result setObject:arr forKey:key];
arr = nil;
[dictionary removeAllObjects];
dictionary = nil;
}
[result1 removeAllObjects];
result1 = nil;
/*--------------------------------------------------------------*/
if (result.count > 0) {
_streetsDictionary = result;
result = nil;
return _streetsDictionary;
}else {
_streetsDictionary = nil;
return nil;
}
}
Why do I get this message?
How can I fix it?
The most likely cause for the crash is trying to access an object that has already been deallocated.
Since it seems that the failure arises on the line:
NSMutableDictionary *isSet = [result1 objectForKey:[NSNumber numberWithInt:[key hash]]];
I would suggest splitting the statement down to its component to try and track down which object could actually be the culprit:
NSInteger h = [key hash];
NSNumber n = [NSNumber numberWithInt:h];
...
but this bug is being created only when in another thread file is being downloaded
Also, check if the downloading code and the crashing code have anything in common. The former might be causing the deallocation of an object used in the second.
Hope it helps.
i have the following code
inAppKeys = [[MKStoreManager sharedManager] purchasableObjectsDescription ];
NSMutableArray * unremovableArray = [[NSMutableArray alloc] init];
for(int i = 0; i<[inAppKeys count]; i++){
for (int j=0; j< [categories count]; j++) {
NSString * inAppKey = [[categories objectAtIndex:j] valueForKey:#"inAppKey"];
if([inAppKey isEqualToString: [inAppKeys objectAtIndex:i]]){
[unremovableArray addObject:[categories objectAtIndex:j]];
}
}
}
categories = [[NSMutableArray alloc] init];
[categories addObjectsFromArray:unremovableArray];
where categories is nsmutablearray .. the thing is addObjectsFromArray leave the categories empty .. what do i do wrong?
Looks to me like you're referring to [categories count] and [categories objectAtIndex:j] before you even alloc/init categories.
Having re-read your title ("reinitializing") which suggests you've previously inited categories, I'm now assuming that you have a master set of categories that you're trying to reduce to the ones actually purchased. If so, I wouldn't re-use the variable "categories" as that's confusing. (I assume categories was auto-released, or else you've got a leak). How 'bout using unremovableArray instead of leaking it?
I'd also use fast enumerators for clarity and speed...
NSLog(#"categories: %#", categories);
inAppKeys = [[MKStoreManager sharedManager] purchasableObjectsDescription ];
NSLog(#"inAppKeys:%#", inAppKeys);
NSMutableArray * unremovableCategories = [[NSMutableArray alloc] init];
for(NSString* thisAppKey in inAppKeys) {
for (NSDictionary* thisCategory in categories) {
if ([[thisCategory valueForKey:#"inAppKey"] isEqualToString: thisAppKey]){
[unremovableCategories addObject:thisCategory];
break; //having added this category; no reason to continue looking at it
}
}
}
//now use unremovableCategories...
his guys,
i think this is a simple question but i do not know how to do it.
how do i create the line below dynamically from an array?
this is what i need to call.
//data source
NSString * sourceData[7] = {#"2", #"1", #"4", #"8", #"14", #"15", #"10"};
chartData = [WSData dataWithValues:[WSData arrayWithString:sourceData withLen:7]];
+ (NSArray *)arrayWithString:(NSString *[])strings
withLen:(NSUInteger)len {
NSMutableArray *tmpArr = [NSMutableArray
arrayWithCapacity:len];
NSUInteger i;
for (i=0; i<len; i++) {
[tmpArr addObject:strings[i]];
}
return [NSArray arrayWithArray:tmpArr];
}
thanks for all the help especially Daniel :)
this is the answer to the question
NSMutableArray * dayArray = [[NSMutableArray alloc] init];
dayArray = [NSMutableArray arrayWithCapacity:7];
NSMutableArray * sdArray = [[NSMutableArray alloc] init];
sdArray = [NSMutableArray arrayWithCapacity:7];
NSInteger drunked = [appDelegate.drinksOnDayArray count];
if (drunked !=0)
{
for(int i=6; i>=0; i--)
{
DayOfDrinks *drinksOnDay = [appDelegate.drinksOnDayArray objectAtIndex:i];
NSString * dayString= [NSDate stringForDisplayFromDateForChart:drinksOnDay.dateConsumed];
[dayArray addObject:dayString];//X label for graph the day of drink.
drinksOnDay.isDetailViewHydrated = NO;
[drinksOnDay hydrateDetailViewData];
NSNumber *sdNumber = drinksOnDay.standardDrinks;
[sdArray addObject: sdNumber];
}
NSString *sData[7];// = malloc(7 * sizeof(NSString *));
for (int i=0; i<7; i++)
{
DayOfDrinks *drinksOnDay = [appDelegate.drinksOnDayArray objectAtIndex:i];
sData[i] = [NSString stringWithFormat:#"%#",drinksOnDay.standardDrinks];
}
NSString * sourceData[7] = {sData[6],sData[5],sData[4],sData[3],sData[2],sData[1],sData[0] };
}
If you are only using the array as a call parm, and are not storing it somewhere or returning it from your current method:
NSString* sourceData[7];
for (i = 0; i < 7; i++) {
int num = <getTheValueYouWant>;
sourceData[i] = [NSString stringWithFormat:#"%d", num];
}
But note that if you intend to return the array, or store it in some long-lived variable, you need an entirely different setup.
So this is how you would create an NSMutableArray. Mutable because you're creating it at runtime.
NSString * sourceData = [[NSString alloc] initWithFormat:#""];
//assuming the array you have is arr with NSNumber objects
for (NSNumber *num in arr) {
[sourceData stringByAppendingFormat:#"%#", num];
}
You can try below code with the loop as you required.....
NSMutableArray *array;
array = [[NSMutableArray alloc] init];
[array addObject:[NSNumber numberWithFloat:1.0f]];
[array release];
Been running instruments on my app. Its says i am leaking 864bytes & 624bytes from 2 NSCFString and the library responsible is Foundation.
So that leads me to believe thats its not a leak caused by me? Or is it?
Here is the offending method according to instruments. It seems to be a
substringWithRange
that is leaking.
-(void) loadDeckData
{
deckArray =[[NSMutableArray alloc] init];
NSString* path = [[NSBundle mainBundle] pathForResource:#"rugby" ofType:#"txt"
inDirectory:#""];
NSString* data = [NSString stringWithContentsOfFile:path encoding:
NSUTF8StringEncoding error: NULL];
NSString *newString = #"";
NSString *newline = #"\n";
NSString *comma = #",";
int commaCount = 0;
int rangeCount = 0;
NSString *nameHolder = #"";
NSString *infoHolder = #"";
NSMutableArray *statsHolder = [[NSMutableArray alloc] init];
for (int i=0; i<data.length; i++)
{
newString = [data substringWithRange:NSMakeRange(i, 1)];
if ([newString isEqualToString: comma]) //if we find a comma
{
if (commaCount == 0)// if it was the first comma we are parsing the
NAME
{
nameHolder = [data substringWithRange:NSMakeRange(i-
rangeCount, rangeCount)];
}
else if (commaCount == 1)//
{
infoHolder = [data substringWithRange:NSMakeRange(i-
rangeCount, rangeCount)];
//NSLog(infoHolder);
}
else // if we are on to 2nd,3rd,nth comma we are parsing stats
{
NSInteger theValue = [[data
substringWithRange:NSMakeRange(i-rangeCount,rangeCount)]
integerValue];
NSNumber* boxedValue = [NSNumber
numberWithInteger:theValue];
[statsHolder addObject:boxedValue];
}
rangeCount=0;
commaCount++;
}
else if ([newString isEqualToString: newline])
{
NSInteger theValue = [[data substringWithRange:NSMakeRange(i-
rangeCount,rangeCount)] integerValue];
NSNumber* boxedValue = [NSNumber numberWithInteger:theValue];
[statsHolder addObject:boxedValue];
commaCount=0;
rangeCount=0;
Card *myCard = [[Card alloc] init];
myCard.name = nameHolder;
myCard.information = infoHolder;
for (int x = 0; x < [statsHolder count]; x++)
{
[myCard.statsArray addObject:[statsHolder
objectAtIndex:x]];
}
[deckArray addObject:myCard];
[myCard autorelease];
[statsHolder removeAllObjects];
}
else
{
rangeCount++;
}
}
[statsHolder autorelease];
}
Thanks for your advice.
-Code
As Gary's comment suggests this is very difficult to diagnose based on your question.
It's almost certainly a leak caused by you however, I'm afraid.
If you go to the View menu you can open the Extended Detail. This should allow you to view a stack trace of exactly where the leak occurred. This should help diagnose the problem.
When to release deckArray? If deckArray is a class member variable and not nil, should it be released before allocate and initialize memory space?
In my iPhone Project when i select build and analyze (shift + mac + A ) it will give me all potential memory leak in my project... but in my current project it is not working... when i intentionally put a memory leak and select build and analyze... it doesn't give me any potential memory leak as analyzer result
if i write
NSMutableArray *tempArray = [[NSMutableArray alloc] initWithCapacity:6];
NSMutableArray *tempArrayfinal = [[NSMutableArray alloc] initWithCapacity:12];
and doesn't release it... it is not giving me any potential leak but if i write
NSString *leakyString = [[NSString alloc] initWithString:#"Leaky String "];
NSLog(#"%#",leakyString);
here it gives me potential leak as analyzer result...why it is not giving potential leak in NSMutableArray and why it gives potential leak in NSString ?... how can i rely on Build and analyze for memory leak...
I've run the app with Leak tool and it is showing me leak in tempArray and tempArrayfinal
Here is my function
- (void)viewDidLoad
{
[super viewDidLoad];
maxOnSnaxAppDelegate *delegate = (maxOnSnaxAppDelegate *)[[UIApplication sharedApplication] delegate];
lblMessage.tag = MESSAGE_LABEL;
lblGuess.tag = GUESS_LABEL;
lblScore.tag = SCORE_LABEL;
self.gameCompleteView.tag = FINAL_SCORE_VIEW;
lblFinalScore.tag = FINAL_SCORE_LABEL;
lblGuess.text = #"";
lblMessage.text = #"";
lblScore.text = #"";
int row = 0;
int column = 0;
maxImagrArray = [[NSMutableArray alloc] init];
for(UIView *subview in [self.view subviews]) {
if([subview isKindOfClass:[CustomImageView class]])
{
[subview removeFromSuperview];
}
}
for(int i = 0 ; i < 12 ; i++)
{
if(i%3 == 0 && i != 0)
{
row++;
column = -1;
}
if(i != 0 )
{
column++;
//row = 0;
}
CustomImageView *tempImageView = [[CustomImageView alloc] initWithImage:[UIImage imageNamed:#"max-img.png"]];
tempImageView.frame = CGRectMake((column*tempImageView.frame.size.width) + 45, (row*tempImageView.frame.size.height)+ 60, tempImageView.frame.size.width, tempImageView.frame.size.height);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(context, tempImageView.bounds);
[self.view addSubview:tempImageView];
tempImageView.tag = i+1;
tempImageView.userInteractionEnabled = YES;
[maxImagrArray addObject:tempImageView];
[tempImageView setIndex:i];
[tempImageView release];
}
NSMutableArray *tempArray = [[NSMutableArray alloc] initWithCapacity:6];
NSMutableArray *tempArrayfinal = [[NSMutableArray alloc] initWithCapacity:12];
for(int i = 0 ; i < 12 ; i++)
{
if(i < 6)
{
int temp = (arc4random() % 10) + 1;
NSString *tempStr = [[NSString alloc] initWithFormat:#"%d",temp];
[tempArray insertObject:tempStr atIndex:i];
[tempArrayfinal insertObject:tempStr atIndex:i];
[tempStr release];
}
else
{
int temp = (arc4random() % [tempArray count]);
[tempArrayfinal insertObject: (NSString *)[tempArray objectAtIndex:temp] atIndex:i];
//int index = [(NSString *)[tempArray objectAtIndex:temp] intValue];
[tempArray removeObjectAtIndex:temp];
}
CustomImageView *tmpCustom = [maxImagrArray objectAtIndex:i];
tmpCustom.frontImageIndex = [(NSString *)[tempArrayfinal objectAtIndex:i] intValue];
NSLog(#"%d",tmpCustom.frontImageIndex);
}
[maxImagrArray release];
delegate.time = 60.0;
timer = nil;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(countDown) userInfo:nil repeats:YES];
delegate.view = self.view;
//[tempArray release];
//[tempArrayfinal release];//these 2 lines are deliberately commented to see
//...it is not showing any potential memory leak though....
delegate.viewController = self;
}
please help...
[tempArray insertObject:tempStr atIndex:i];
[tempArrayfinal insertObject:tempStr atIndex:i];
are the culprits... when i uncomment these 2 lines.. it stops giving me the warning... i don't know why...
You shouldn't really rely on the Build and Analyze tool. It does not always catch all leaks. Threre is no substitute for following the memory management rules from apple (apart from garbage collection on OS X). However, I'm not sure why it isn't catching such a simple leak. I tried at line in a method and it did give me a result. Are you sure its not in an if statement, because I've found that sometimes in an if statement it won't correct you.