Memory leaking worse than a turned on faucet

Discussion in 'Mac Programming' started by slooksterPSV, Aug 1, 2006.

  1. macrumors 68030

    slooksterPSV

    Joined:
    Apr 17, 2004
    Location:
    Nowheresville
    #1
    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?
     
  2. Guest

    caveman_uk

    Joined:
    Feb 17, 2003
    Location:
    Hitchin, Herts, UK
    #2
    NSMutableArray* newArray=[NSMutableArray arrayWithArray: otherArray];

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

    both give should give mutable autoreleased arrays
     
  3. thread starter macrumors 68030

    slooksterPSV

    Joined:
    Apr 17, 2004
    Location:
    Nowheresville
    #3
    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.
     
  4. macrumors 603

    whooleytoo

    Joined:
    Aug 2, 2002
    Location:
    Cork, Ireland.
    #4
    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).
     
  5. thread starter macrumors 68030

    slooksterPSV

    Joined:
    Apr 17, 2004
    Location:
    Nowheresville
    #5
    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.
     
  6. macrumors 603

    whooleytoo

    Joined:
    Aug 2, 2002
    Location:
    Cork, Ireland.
    #6
    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] ;
        ...
    }
    
     
  7. thread starter macrumors 68030

    slooksterPSV

    Joined:
    Apr 17, 2004
    Location:
    Nowheresville
    #7
    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?
     
  8. macrumors 603

    whooleytoo

    Joined:
    Aug 2, 2002
    Location:
    Cork, Ireland.
    #8
    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.
     
  9. thread starter macrumors 68030

    slooksterPSV

    Joined:
    Apr 17, 2004
    Location:
    Nowheresville
    #9
    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.
     
  10. macrumors 603

    whooleytoo

    Joined:
    Aug 2, 2002
    Location:
    Cork, Ireland.
    #10
    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.
     
  11. thread starter macrumors 68030

    slooksterPSV

    Joined:
    Apr 17, 2004
    Location:
    Nowheresville
  12. thread starter macrumors 68030

    slooksterPSV

    Joined:
    Apr 17, 2004
    Location:
    Nowheresville
    #12
    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.
     
  13. thread starter macrumors 68030

    slooksterPSV

    Joined:
    Apr 17, 2004
    Location:
    Nowheresville
    #13
    Screenshot!
     

    Attached Files:

Share This Page