Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

slooksterPSV

macrumors 68040
Original poster
Apr 17, 2004
3,544
306
Nowheresville
Ok I'm having big issues with memory leakages in my app, I figured out how to change between different accounts on the left side, I uploaded my app in another thread, but here's the updated code that I have for on section.
Code:
- (void)showTransactionsForAccount:(id)sender
{
	NSLog(@"You chose %d", [accountView selectedRow]);
	if([accountView selectedRow] >= 0)
	{
		NSMutableArray *transAcct = [[NSMutableArray alloc] initWithArray:[[accounts objectAtIndex:
			[accountView selectedRow]]transactions]];
		NSLog(@"%@", transAcct);
		if(transAcct != nil) {
		//[transactions release];
		transactions = transAcct;
		[self setTransactions:transactions];
		[tableView setNeedsDisplay:YES];
		}
	}
}

I'm thinking my leak is with the mutable array being allocated with an array, but never being released. Is there a function where I can put an array in the array without allocating it again?
 

caveman_uk

Guest
Feb 17, 2003
2,390
1
Hitchin, Herts, UK
NSMutableArray* newArray=[NSMutableArray arrayWithArray: otherArray];

I think that should work. Failing that use [[array mutableCopy] autorelease]

both give should give mutable autoreleased arrays
 

slooksterPSV

macrumors 68040
Original poster
Apr 17, 2004
3,544
306
Nowheresville
caveman_uk said:
NSMutableArray* newArray=[NSMutableArray arrayWithArray: otherArray];

I think that should work. Failing that use [[array mutableCopy] autorelease]

both give should give mutable autoreleased arrays
I'm grabbing an array from an array, is that bad? So I have an array called Accounts which holds arrays of transactions which hold data.
Accounts->Transactions->name, date, current balance, avail balance, total

EDIT: and the array is being created constantly, like whenever you click on an area, it creates one, click to another it creates another, etc. etc. etc.

EDIT 2: transAcct = [NSMutableArray arrayWithArray:[[accounts objectAtIndex:
[accountView selectedRow]]transactions]];
the program crashes there when you switch back and forth between data cells.
 

whooleytoo

macrumors 604
Aug 2, 2002
6,607
716
Cork, Ireland.
slooksterPSV said:
Code:
- (void)showTransactionsForAccount:(id)sender
{
	NSLog(@"You chose %d", [accountView selectedRow]);
	if([accountView selectedRow] >= 0)
	{
		NSMutableArray *transAcct = [[NSMutableArray alloc] initWithArray:[[accounts objectAtIndex:
			[accountView selectedRow]]transactions]];
		NSLog(@"%@", transAcct);
		if(transAcct != nil) {
		//[transactions release];
		transactions = transAcct;
		[self setTransactions:transactions];
		[tableView setNeedsDisplay:YES];
		}
	}
}

Ok, there are a few problems here.

- As caveman_uk pointed out, you're creating transAcct each time, and not releasing it.

- You can use arrayWithArray instead, but since that returns an autoreleased array, you may need to retain it (either here, or in setTransactions: ), and release it again later.

- Assuming transactions is an instance variable, do you even need to create another array pointer, "transAcct"? (Not a bug, just a suggestion). You "should" also use an accessor method rather than setting its value directly (it's not compulsory, but it avoids release/retain confusion later).
 

slooksterPSV

macrumors 68040
Original poster
Apr 17, 2004
3,544
306
Nowheresville
whooleytoo said:
Ok, there are a few problems here.

- As caveman_uk pointed out, you're creating transAcct each time, and not releasing it.

- You can use arrayWithArray instead, but since that returns an autoreleased array, you may need to retain it (either here, or in setTransactions: ), and release it again later.

- Assuming transactions is an instance variable, do you even need to create another array pointer, "transAcct"? (Not a bug, just a suggestion). You "should" also use an accessor method rather than setting its value directly (it's not compulsory, but it avoids release/retain confusion later).

transactions is what holds the transactions when the user creates one, then I want to store that into a variable (which is a NSMutableArray) in my account which holds an array of the transactions.

Account->Transactions->Transaction data
Transactions->Transaction data

I'll try #2 since I have a pretty good idea of what you're saying, but #3, what kind of accessor would I create? one that calls what the long line I have?

EDIT: Errors again now
Code:
2006-08-01 11:05:16.868 MDM[2649] You chose 0
2006-08-01 11:05:16.868 MDM[2649] ()
MDM(2649,0xa000ed98) malloc: *** error for object 0x39e1d0: double free
MDM(2649,0xa000ed98) malloc: *** set a breakpoint in szone_error to debug
2006-08-01 11:05:21.739 MDM[2649] You chose 0
2006-08-01 11:05:21.739 MDM[2649] ()
MDM(2649,0xa000ed98) malloc: *** error for object 0x3ac540: double free
MDM(2649,0xa000ed98) malloc: *** set a breakpoint in szone_error to debug

EDIT 2:
Code:
		transAcct = [NSMutableArray arrayWithArray:[[accounts objectAtIndex:
			[accountView selectedRow]]transactions]];
is the line it crashes on when I retain it, store items in it, and then at the end, release it.

EDIT 3:
and it only crashes when there are transactions in each account.
 

whooleytoo

macrumors 604
Aug 2, 2002
6,607
716
Cork, Ireland.
slooksterPSV said:
I'll try #2 since I have a pretty good idea of what you're saying, but #3, what kind of accessor would I create? one that calls what the long line I have?

I'd write it something like this (apologies if I misunderstand what you're trying to do!)

Code:
- (void) setTransactionsForAccount: (id) sender
{
    if ([accountView selectedRow] >= 0)
    {
        NSMutableArray* selectedTrans = [NSMutableArray arrayWithArray: [[accountView selectedRow] transactions] ;
        if (selectedTrans)
            [self setTransactions: selectedTrans] ;
        [tableView setNeedsDisplay:YES] ;
    }
}

- (void) setTransactions: (NSMutableArray*) transactions
{
    if (transactions != _transactions)
    {
        [_transactions release] ;
        _transactions = [transactions retain] ;
    }
}

// And, in your dealloc..

- (void) dealloc
{
    ...
    [_transactions release] ;
    ...
}
 

slooksterPSV

macrumors 68040
Original poster
Apr 17, 2004
3,544
306
Nowheresville
If you didn't catch Edit 2 and 3, see above or below (whichever you have your threads set on to show)

EDIT:
Code:
		NSMutableArray* selectedTrans = [NSMutableArray arrayWithArray: [[accounts objectAtIndex:[accountView selectedRow]] transactions]] ;
I had to change it to that, cause accounts is an array, and its taking the object with the location of the selected row which is an array, so it copies that array into the array. So it gets the array in an array. Is that ok?
 

whooleytoo

macrumors 604
Aug 2, 2002
6,607
716
Cork, Ireland.
slooksterPSV said:
If you didn't catch Edit 2 and 3, see above or below (whichever you have your threads set on to show)

If you're having trouble with that line, I'd break it down into its constituents and step through it, and see exactly where the problem is, i.e.

Code:
                NSMutableArray *transAcct = [[NSMutableArray alloc] initWithArray:[[accounts objectAtIndex:
                        [accountView selectedRow]]transactions]];

becomes..

Code:
int selectedRow = [accountView selectedRow] ;
id account = [accounts objectAtIndex: selectedRow] ;
id array = [account transactions] ;
NSMutableArray* transAcct = [[NSMutableArray alloc] initWithArray: array] ;

It should be pretty obvious at that point where the problem lies.
 

slooksterPSV

macrumors 68040
Original poster
Apr 17, 2004
3,544
306
Nowheresville
EDIT: Does this mean anything to ya?
If I have 3 accounts, and 2 of them are empty, and I click on one that has data in it, then switch back and forth between the 2 empty ones, nothing happens, but once I click on that one that has data, BAM crashes.

EDIT2: now I just got
Code:
2006-08-01 11:33:14.815 MDM[2892] [<Account 0x3a5b00> valueForUndefinedKey:]: this class is not key value coding-compliant for the key date.



NSMutableArray* selectedTrans = [[NSMutableArray alloc] initWithArray: array];

is the problem if I release the object after its done its function. e.g.

NSMutableArray* selectedTrans = [[NSMutableArray alloc] initWithArray: array];
if (selectedTrans)
{
[self setTransactions: selectedTrans];

}
[selectedTrans release];

otherwise it works if I don't release it, but that uses gobs of memory.
 

whooleytoo

macrumors 604
Aug 2, 2002
6,607
716
Cork, Ireland.
slooksterPSV said:
NSMutableArray* selectedTrans = [[NSMutableArray alloc] initWithArray: array];

is the problem if I release the object after its done its function. e.g.

NSMutableArray* selectedTrans = [[NSMutableArray alloc] initWithArray: array];
if (selectedTrans)
{
[self setTransactions: selectedTrans];

}
[selectedTrans release];

otherwise it works if I don't release it, but that uses gobs of memory.

Assuming you need to "hang on to" the selectedTrans array (perhaps to draw another table view?), you can't release it as above; your program would likely crash later on when trying to draw the table view.

Of course, if you don't release it, it just leaks.

I'd recommend using the setTransactions: method I posted above. (You may have other code in your setTransactions: method already, which you could add to mine above). This would ensure that every time you change selection, the old transaction array is released, and the new one retained.
 

slooksterPSV

macrumors 68040
Original poster
Apr 17, 2004
3,544
306
Nowheresville
I GOT IT, I GOT IT, IT WORKS YAY!!!
Only one problem left thought :(

Whenever I quit the program it crashes, and it crashes when I try to set the transaction to nil. Not sure if I need to do this, but it does remove observers. Hmm.. I'm going to try remove setTransactions:nil and just release transactions, there are 0 objects in it at the end so yeah.
 

slooksterPSV

macrumors 68040
Original poster
Apr 17, 2004
3,544
306
Nowheresville
Screenshot!
 

Attachments

  • Picture 1.png
    Picture 1.png
    41.5 KB · Views: 79
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.