My Cocoa Bits

2012.02.23

Balancing malloc() and free()

Filed under: Memory management,Objective-C — rtovars @ 00.40

It’s been a long time since my last post, but I’ve been really busy with the release of my first iPhone app: BibleMemoryFlashCards (yes, I know it’s a long name, but the original one was already taken) and then I’ve been working with my second app which I hope to release soon.

While testing and profiling my current project I found a leak that was causing me some problems because I didn’t know when to release memory. The problem basically happened in a function that returned an array of NSIntegers created using malloc().

-(NSInteger *)generateBoard:(NSString *)aSequence {
	NSArray *tokens = [aSequence componentsSeparatedByString:@"/"];
	NSInteger tempBoard[SSMAX_BOARD_INDEX];
	NSInteger i = -1;

	// Convert the array of strings to a simple array of numbers
	for (NSString *token in tokens) {
		tempBoard[++i] = [token intValue];
	}
	NSInteger *boardRef = malloc(sizeof(tempBoard));
	memcpy(boardRef, tempBoard, sizeof(tempBoard));

	return boardRef;
}

The Static Analyzer indicated me there was a memory leak in this line:

NSInteger *boardRef = malloc(sizeof(tempBoard));

Now, most of the answers I found in Google just mentioned that any call to malloc() should be balanced with a corresponding call to free(), so the previously allocated memory could be safely released, thus avoiding the impending memory leak.

I was wondering what could be the proper place to free memory, since I couldn’t do it within the same function where I allocated memory for my array, because I returned the pointer to the calling method. In the end I released memory in three different places:

  1. In the setter method used to store the pointer.
  2. In the dealloc() method of the class to which the instance variable belongs.
  3. In an external call to the generateBoard: method.

1. The setter method ended up looking like this:

-(void)setWorkingBoard:(NSInteger *)aBoard {
	if (workingBoard != nil) {
		free(workingBoard);
	}
	workingBoard = aBoard;
}

This was necessary because in some places I just reassigned the pointer to new data, and consequently I was loosing the reference to the old allocated data, causing a leak.

2. dealloc() is the place where data cleanup is done, so I also called free() on the two pointers I use as instance variables in my class.

3. This was not so intuitive, but the Leaks Instrument indicated the following line was causing another memory leak:

SSShufflingArray *shufflingArray = [[SSShufflingArray alloc] initWithNSIntegerArray:[self generateBoard:self.sequence]];

The problem was that the call to [self generateBoard:self.sequence] created a pointer and there was no reference I could use to free memory, so I had to break this line in two:

NSInteger *tempBoard = [self generateBoard:self.sequence];
SSShufflingArray *shufflingArray = [[SSShufflingArray alloc] initWithNSIntegerArray:tempBoard];

Then I could use free(tempBoard); to release memory referenced by the returned pointer.

After these and a couple of other changes involving releasing objects, I checked again for memory leaks and this time Instruments didn’t report any problem.

2011.11.24

Display local HTML and images within a UIWebView

Filed under: Design,Graphics,Icons,Objective-C — rtovars @ 21.41

I wanted to include a quick help file for my iPhone app, just in case, although Apple’s “iOS Human Interface Guidelines” document mentions that all iOS apps should be intuitive and easy to use and so onscreen help should be minimal. Still, I wanted to provide this as a little help is always welcome.

The first implementation loaded a local HTML file containing just text:

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"<filename>" ofType:@"<extension>"];

[myUIWebView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:filePath]]];

(You can replace <filename> and <extension> by the real name and extension of your local HTML file).

In my help file I wanted to include some images that appear in one of the lists I use in the app, so I did some research and I found this excellent blog with the answer I was looking for. The final implementation was just some lines longer:

NSError *error;

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"<filename>" ofType:@"<extension>"];

NSString *htmlString  = [NSString stringWithContentsOfURL:[NSURL fileURLWithPath:filePath] usedEncoding:nil error:&error];

NSString *basePath = [[NSBundle mainBundle] bundlePath];

NSURL *baseURL = [NSURL fileURLWithPath:basePath];

[myUIWebView loadHTMLString:htmlString baseURL:baseURL];

Within the HTML file images are inserted with a simple line:

<img src="image.png"/>

The result is formatted text and embedded images in a scrollable view that hopefully will provide useful tips to the users!

EXC_BAD_ACCESS error when using the ‘assign’ declared property attribute

Filed under: Memory management,Objective-C — rtovars @ 12.21

In my previous post titled  EXC_BAD_ACCESS error, I mentioned the problems caused by not retaining an object, which lead to my code trying to access an already released object, triggering the EXC_BAD_ACCESS error.

I began refactoring my code and when I tested part of the functionality I found again the error, and it was really hard to spot, as Instruments just gave a hint that a zombie object was being called, but the highlighted line was nowhere near the real source. The problem was not that the object was being overreleased, but that it was not retained in the first place. The offending line was this:

@property (nonatomic, assign) UILabel *answer;

I didn’t notice that when I rewrote this line I didn’t use the retain attribute for the declared property. Then, in my implementation file, I sent a release message to the object in the dealloc method, and this is where the error occurred, as I was releasing an object for which I hadn’t previously claimed ownership and so I was decreasing the retain count to -1. When I replaced the assign attribute to retain, the problem was solved.

The bright side of this error was that I learned to use Instruments.

Keep up coding!

2011.11.17

UIButton bug when setting text in titleLabel property

Filed under: Design,Objective-C — rtovars @ 19.41

My app has a Settings screen to adjust different parameters; one of the options is to reset test statistics. My app is currently localized for English and Spanish, and in most of the nibs I just set up generic text in the controls and then I programmatically change the text using NSLocalizedStrings, except for the main screen, which contains a TabBar (UITabBar) root controller. In this case I localized the nib and my project ended up with two nib files, which is not that hard to maintain.

However, for the Settings screen I wanted to maintain a single nib, and I’d programmatically change the text of each control. This works fine for UILabels, but the UIButton control seems to have a bug, according to this question in stackoverflow.

If you leave the button’s text blank in the nib and you change that in code, the button remains blank. According to the answer mentioned before, what I did was to assign a default text to the button and this time the change done in code worked BUT the text wasn’t displayed in its entirety, it got truncated like this: “Reset t…tistics”. Then, to solve this I assigned a larger default text in the nib and this time it worked, I could see the whole label: “Reset test statistics”.

However, sometimes when I clicked on the button the text changed again to the larger default text I had initially set in the nib. I found this answer in stackoverflow. In the end, my code looked like this:

[resetButton setTitle:NSLocalizedString(@"resetButton", "") forState:UIControlStateNormal];

[resetButton.titleLabel setTextAlignment:UITextAlignmentCenter];

It seems this behavior is a bug in iOS5, but I couldn’t verify it as I haven’t registered as an Apple Developer and I can’t see the Forums yet. I’ll keep this bug in mind when I request membership to the Apple Developer Program, which will be when my app has been polished enough that I won’t have to spend more time fixing things and thus wasting membership time.

Keep this workaround in mind when localizing your UIButtons!

2011.11.10

EXC_BAD_ACCESS error

Filed under: Memory management,Objective-C — rtovars @ 13.36

I’m in the process of implementing the main functionality of my iPhone application. At some point during my tests I found the EXC_BAD_ACCESS error after retrieving an object’s data.

The calling method where the error happened used the following line to retrieve data coming from a Singleton:

testLists = [[SSEngine sharedEngine] testLists]; // Error happens here!

The Singleton method that returns the data looks like this:

-(NSArray *)testLists {
    return [currentUser.statistics allObjects];
}

The statistics instance variable within the currentUser object returns a NSSet reference, as it was specified by CoreData. Since the calling method requires data to be stored in an NSArray I use the allObjects method to return an array containing the set’s members.

I found some info in Google in the following links in stackoverflow and in a website by Lou Franco. At first I thought my problem was being caused by some faulty implementation of CoreData data reading and/or writing, but after going through both of these posts it was clear the root cause was in some object that was either not retained or released too early.

As Lou Franco suggested in his post, I ran the Analyze command in Xcode 4 and it immediately pointed to the first line of code above, indicating the object’s retain count might be improperly updated, which could cause early deallocation, thus the dreaded EXC_BAD_ACCESS error I was getting.

I updated the line to look like this:

testLists = [[[SSEngine sharedEngine] testLists] retain];

This time my application didn’t crash when I tried to use the testLists variable. I thought about how memory is being managed in this case and I came with the following explanation:

  1. The allObjects method returns a new NSArray object, so there’s no explicit reference to it and consequently no explicit retain.
  2. When the new NSArray was returned to the calling method it was immediately released and I ended up working with a dangling pointer, which caused the EXC_BAD_ACCESS error.

Once I retained the returned NSArray I took ownership of the new object and then all references to it were still valid.

Lesson learned: Always double check to make sure I’m taking ownership of an object I’ll use at a later time.

Happy coding!

2011.11.02

How to shuffle the contents of an array?

Filed under: Objective-C — rtovars @ 18.12

In my application I need to shuffle an array of numbers, and after doing some research on Google I found this useful article in Wikipedia: Fisher–Yates shuffle.

There’s  a couple of algorithms explained in the article, but the one I found more useful is the one known as the modern version of the Fisher–Yates shuffle algorithm by Richard Durstenfeld. I basically implemented it using an NSMutableArray and the method looks like this:

-(void)shuffle {
    int j = 0;
    id tempElement = nil;

    for (int i = [embeddedArray count] - 1; i >= 1; i--) {
        j = arc4random_uniform(i+1);
        tempElement = [embeddedArray objectAtIndex:i];
        [embeddedArray replaceObjectAtIndex:i withObject:[embeddedArray objectAtIndex:j]];
        [embeddedArray replaceObjectAtIndex:j withObject:tempElement];
    }
}

The Wikipedia article mentions: “Properly implemented, the Fisher–Yates shuffle is unbiased, so that every permutation is equally likely. The modern version of the algorithm is also rather efficient, requiring only time proportional to the number of items being shuffled and no additional storage space.”

My application is not math intensive, so I think this implementation works fine.

Working with C int * arrays as class instance variables

Filed under: Objective-C — rtovars @ 17.50

It’s been a while since my last post, but here it goes: I started coding my app’s main classes, and for this particular implementation I needed to store a sequence of ints in an instance variable, so the obvious choice was an NSArray. However, for the sake of performance I thought it would be better to store these numbers in a simple C array of ints.

The instance variable was declared in class MyList like this:
int *bookList;

and the corresponding declared property as follows:
@property (nonatomic) int *bookList;

Then, in the class that acts as a central controller I created my instances using this syntax:
MyList *aList = [[MyList alloc] init];
[aList setBookList:(int []){1, 2, 3, 0}];

When I tested this approach I confirmed data was being stored as expected, at least when I printed the object’s contents of the int array in the same code block where I declared the arrays. The problem was when I tried to print this data in a different method which received the MyList object as a parameter:
-(void)displayMyList:(MyList *)theList {
// Print the contents of the int array
}

When I tested this code, the NSLog statements kept printing strange values presumably contained in the int array. I debugged and couldn’t find where these the original values were being modified, because the pointer to the int array kept pointing to the same address as before entering, during processing, and after returning from the displayMyList: method.

Finally, after a couple of days of going through chapter 5 of K&R I submitted a question to stackoverflow and this is the answer I got.

So, I updated my code to look like this when creating and assigning the new int array to the instance variable:

int sourceList[] = {1, 2, 3, 0};
int *bookList = malloc(sizeof sourceList);
memcpy(bookList, sourceList, sizeof sourceList);
[aList setBookList:bookList];

And voilà, this time it worked like a charm. I was able to print the contents of the bookList instance variable using this for cycle:

for (int i = 0; i < 4; i++) {
    NSLog(@"bookList[%d] = %d", i, myList.bookList[i]);
}

Hope this post will help someone. Nice coding!

2011.10.10

“Expected expression” error using switch statement

Filed under: Uncategorized — rtovars @ 20.15

I’m going through Chapter 19 (View Controllers) of Matt Neuburg’s Programming iOS 4 [Kindle edition]. I wanted to “reuse” one of my projects to test a concept in the book, so instead of commenting or deleting the previous code, I decided to create a switch block so each case would contain a working code sample, just the way Mr. Neuburg does.

Right after I pasted my old (working) code, the compiler complained and showed an “Expected expression” error in the fist line after the case, where I declared a variable. This seems to be a common error, and yet it puzzled me for half an hour while I was reading my code again and again until I decided to ask Mr. Google. Luckily for me, I found the answer right away in stackoverflow:

“… in C it’s illegal to have a declaration as the first statement after a label — note that the compiler expects an expression, such as a method call, normal assignment, etc. (Bizarre though it may be, that’s the rule.)”

There are two ways to circumvent this rule:

  1. Add an expression between the case and the first line, such as a simple NSLog statement, or
  2. Enclose the whole block within curly braces {}
I went for the second option and the error disappeared. Oddly enough, there’s a comment in the post saying this behavior is not exclusive to C, but also happens in Java. I guess this never happened to me before because I never tried to declare a variable as the first statement after a case. Anyway, mystery solved and now I’m going back to work =)
Keep coding!

2011.10.07

Declared properties not backed up by instance variables

Filed under: Objective-C — rtovars @ 13.43

The other book I mentioned in my review of Neil Smyth’s iPhone iOS 4 Development Essentials – Xcode 4 Edition was Programming iOS 4 [Kindle edition] by Matt Neuburg. Probably I’ll write a review of this book after I read it again, but for now what called my attention was that in an example on Chapter 19. View Controllers there’s mention of a declared property without any instance variable backing it up.

I spent some time leafing (can you say that when you’re reading an e-book?) through the book to find a reference to his feature in Objective-C, but I couldn’t find it, and I’m sure I read something about it. Finally I gave up and started searching on stackoverflow and I found the answer here.

The thing to remember is: The @property compiler directive in Objective-C 2.0 will automatically generate the instance variable for you if you have not done so; still, there are some cases where instance variables must be provided (paraphrasing the most voted answer) if you:

  1. Need to directly access them for some advanced reason
  2. You want subclasses to be able to access the instance variables.
  3. You want your instance variable to have a different name to the property itself (in which case you can use @synthesize myProperty = myInstanceVariable_)
  4. If you plan to run your code on older devices or compile it with older versions.
This seems pretty straightforward, so the only thing to do is stick to a consistent coding style =)

Steve Jobs: A sad note

Filed under: General — rtovars @ 01.18

Steve Jobs (1955 - 2011)

Steve Jobs was a true visionary who believed in what he did, and in doing so served as inspiration for others like us to “think different” and pursue our dreams. No doubt he’ll be remembered for years to come as the man who shaped the world of technology to make it accessible to all, and not only that, but as an artist who created works of art with uncompromising high quality.

Next Page »

Theme: Rubric. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.