Advertise here




Advertise here

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Sign In with Google Sign In with OpenID
Please do not post the same thing multiple times. The board software automatically flags certain posts as needing moderator attention. This happens the most often for new users. I'm pretty sure this is made clear at the time you attempt to post. Posting the same thing over and over again just makes that many more posts the moderators have to weed through later. This makes us sad. Don't make us sad. If your post/thread doesn't appear, just wait a while. Don't post it again. If it hasn't shown up by the next day, then you can try again. I normally go through posts in the mornings, and try to check a few times throughout the day, but I'm not here 24/7. There will typically be a significant delay before posts are approved. Just be patient.

Memory management issue - EXC_BAD_ACCESS

Hi all,

I have just started learning Objective-C, and I'm having a memory management issue. I believe I know which line of code caused the problem (as the program worked before I changed this line)...I just don't know why it failed.

The basic overview of this program is that I am attempting to write a class which will eventually have a few UITableView's in it. Each table will be grouped into sections (and then obviously each of those sections has it's own cells). I wrote my own table and section class to store the data (and subclassed those for specific tables). Initially I have an NSArray of UITableViewCell's in each of the sections to represent the cells in that section. I intend to change that and write my own class for the cells (and initialise the UITableViewCell's on the fly)...but something has gone wrong in the creation of these cells. I really would like to work out what has gone wrong before I change it, as there is something wrong my understanding of memory management as I thought it should have worked (and somewhere between the manual memory management, the loose typing, and the vague compiler messages...I'm kinda worried that this is one of those languages where 'a little knowledge is a dangerous thing' :p ).

For clarity's sake I'll try to go straight to the line I think is causing the problem (and then some context beneath it)...The gist of this is that I'm in my section class, in a helper method which initalises a cell and returns it to be added to an NSArray of UITableViewCells. The NSArray cells is a property of the section object and is set as (retain, nonatomic). The problem is with the initialisation of the icon image for the cell...

I started off with the following which did work:
NSString *imageFile = [[NSBundle mainBundle] pathForResource:imagePath ofType:@\"png\"];
cell.imageView.image = [[UIImage alloc] initWithContentsOfFile:imageFile];

Using the above code the cells initialised and the images displayed in the table without a problem.

And then I was reading a book and I saw a convenience method of the UIImage class called imageNamed which I thought would make these two lines neater, and so I tried to implement it instead of the above two lines:
cell.imageView.image = [UIImage imageNamed:@\"image1.png\"]; 


This failed with an EXC_BAD_ACCESS error. I thought the NSArray would take 'ownership' of of the cell (and hence cell image)...but I had also read that class convenience methods have ownership over the objects they create and that you needed to take ownership with the retain keyword, so I tried:
cell.imageView.image = [[UIImage imageNamed:@\"image1.png\"] retain]; 


This also failed with an EXC_BAD_ACCESS error. The image seems to be released before it should be (or something like that). I'm confused about how to handle the memory management here...I thought the couple of lines that worked would be roughly equivalent to the last line of code I posted :confused: . I could just change it back to the lines of code that actually worked but I'm more concerned about why it failed as I'm sure I'll hit a problem like this again.

I did also run NSZombies and got the error:
*** -[CFArray release]: message sent to deallocated instance 0x4b68900

So, something to do with the cells in the array (the only array in the program is the cells array).

Here is the context:

Table:

#import <Foundation/Foundation.h>

@interface Table : NSObject {
NSArray *sections;
}

@property (retain, nonatomic) NSArray *sections;

-(id) init;

@end


TableSection:

#import <Foundation/Foundation.h>
#import \"AppSettings.h\"

@interface TableSection : NSObject {
NSString *heading;
NSArray *cells;
NSString *cellIdentifier;
UITableViewCellAccessoryType cellAccessory;
UITableViewCellStyle cellStyle;
}

@property (retain, nonatomic) NSString *heading;
@property (retain, nonatomic) NSArray *cells;
@property (retain, nonatomic) NSString *cellIdentifier;
@property UITableViewCellAccessoryType cellAccessory;
@property UITableViewCellStyle cellStyle;

-(id) init;
-(void) dealloc;
-(UITableViewCell *) createCell:(NSString *)label pathForImage:(NSString *)imagePath;

@end


And the implementation of the TableSection class:

#import \"TableSection.h\"

@implementation TableSection

@synthesize heading, cells, cellIdentifier, cellAccessory, cellStyle;

...

-(UITableViewCell *) createCell:(NSString *)label
pathForImage:(NSString *)imagePath
{
UITableViewCell *cell = [[UITableViewCell alloc]
initWithStyle:cellStyle
reuseIdentifier:cellIdentifier];
cell.textLabel.text = label;
cell.textLabel.font = [[AppSettings instance] labelFont];

//NSString *imageFile = [[NSBundle mainBundle] pathForResource:imagePath ofType:@\"png\"];
//cell.imageView.image = [[UIImage alloc] initWithContentsOfFile:imageFile];

cell.imageView.image = [[UIImage imageNamed:@\"image1.png\"] retain];

return cell;
}

...

@end


And the createCell method is being called in a subclass of the TableSection class in the subclasses init method like this:

-(id) init
{
self = [super init];
if (self) {
heading = @\"Section heading:\";
UITableViewCell *cell1 = [super createCell:@\"Cell 1\" pathForImage:@\"image1\"];
UITableViewCell *cell2 = [super createCell:@\"Cell 2\" pathForImage:@\"image2\"];
UITableViewCell *cell3 = [super createCell:@\"Cell 3\" pathForImage:@\"image3\"];

cells = [[NSArray alloc] initWithObjects:cell1, cell2, cell3, nil];
}
return self;
}


Can anyone help?
Post edited by Kaitlan on

Replies

  • BrianSlickBrianSlick Posts: 9,313Tutorial Authors, Registered Users
    I don't think you've posted the code that contains the problem. EXC_BAD_ACCESS is indicative of an over-release (or under-retain), but all you are showing here are leaks. Leaks don't crash.

    Leak:

    cell.imageView.image = [[UIImage alloc] initWithContentsOfFile:imageFile];


    Leak:

    cell.imageView.image = [[UIImage imageNamed:@\"image1.png\"] retain];


    This is ok by itself, but depends on what you do with the returned object:

    -(UITableViewCell *) createCell:(NSString *)label 
    pathForImage:(NSString *)imagePath
    {
    UITableViewCell *cell = [[UITableViewCell alloc]
    initWithStyle:cellStyle
    reuseIdentifier:cellIdentifier];
    ...

    return cell;
    }


    ... but you do indeed leak the returned object here:

    UITableViewCell *cell1 = [super createCell:@\"Cell 1\" pathForImage:@\"image1\"];
    UITableViewCell *cell2 = [super createCell:@\"Cell 2\" pathForImage:@\"image2\"];
    UITableViewCell *cell3 = [super createCell:@\"Cell 3\" pathForImage:@\"image3\"];

    cells = [[NSArray alloc] initWithObjects:cell1, cell2, cell3, nil];


    None of these are related to your crash. You are most likely over-releasing something somewhere.


    The whole approach here is really odd. There is very little reason to put cells in your own array. This largely defeats the caching mechanism that table views have.
  • KaitlanKaitlan Posts: 3New Users
    Hi Brian...thanks for the response :)...I do think it quite possible that I have over-released along the way, I did start pulling out release statements at one point because I saw a warning that I had released something that had already been released. I will go back and go through the code...I've been trying to do more reading on the memory management aspect because the one thing this error pointed out was that I don't understand the conventions of object ownership well enough yet. Thanks for going through the code and pointing out the leaks.

    On the second point, yes...the approach/design is very odd and very awkward...it needs redoing...I'm still trying to work out how to adjust to the language features. Back off to the books, I think...

    Cheers.
  • uzauziuzauzi Posts: 11New Users
    Thanks brian. It will really good for all of us
Sign In or Register to comment.