Skip to content

Archive

Tag: memory management

After almost a year, my third update to the ObjC beginner caveats blurb. 8 new caveats added today (marked with [NEW])

Language/SDK

1. NSArray/NSMutableArray cannot hold ints or NSInteger
>> although NSInteger is notationally similar to NSNumber, NSNumber is an object while NSInteger is an alias for int or long (depending on whether you’re running a 32/64 bits architecture). NSArray can only hold objects. If you want to add a number to an NSArray, use NSNumber and initialise your number with something like [NSNumber numberWithInt:26].
(Yes, you can use standard C arrays, there are quite a few posts about this around)

2. NSNumber doesn’t auto-unbox
>> If you try to assign NSNumber to an int (or, better, an NSInteger), you’re assigning a pointer, not the actual number. To get the actual number, use something like: [MyNSNumber integerValue]

3. Strings don’t concatenate with [+] or [.]
>>
If something like “Score: “+score is what you’re used to, try making friends with:
[NSString stringWithFormat:@"Score: %i", score];

4. In, (void)applicationDidFinishLaunching:(UIApplication *)application {…}not all IBOutlets depending on your nib file will initialize until your view is added to the main window
after [window makeKeyAndVisible]; it should be safe to access all IBOutlets attached to your viewController.

5. I updated the frame property of a subview, but the coordinates look incorrect.
>> after updating the UIView.frame property on a subview, invoke setNeedsLayout on the parent view.

6. NSTimer fires at the wrong time / fires too many times
>> When you allocate/init NSTimer with the usual code, you don’t need to invoke fire(). NSTimer is setup as soon as it’s initialized and fire() shouldn’t be called directly as it, *doh!* fires the timer.
>> Whatever you name your callback method, it should take a unique NSTimer argument ( the selector argument would typically look like @selector(myCallback:) with the semi-colon at the end).
What happened to me is that my timer kept firing over and over even though repeat:NO was set. Adding the timer argument to the callback fixed the problem.

7. You cannot declare new variables inside a switch statement

switch (foo) {

case BAR:

char foobar=’*'; // compile error

break;

}

Use this instead:

char foobar;

switch (foo) {

case BAR:

foobar=’*'; // OK

break;

}

Memory Management

8. Use NSZombieEnabled to crash and get a call stack when your program attempts accessing a deallocated object [NEW]

Google it…

9. You need a symbolic breakpoint to hit malloc_error_break and get a call stack [NEW]

Google it (I feel lazy).

10. Unless otherwise stated, objects allocated as a side effect of calling methods other than [alloc] are autoreleased.

This is especially applicable to objects created using factory methods. Take the following example:

[NSMutableArray arrayWithCapacity:5]; // will be released automatically

[[NSMutableArray alloc]initWithCapacity:5]; // we just created a zombie!

At first, it would seem that [NSMutableArray arrayWith...] forms are just shorthands for [[NSMutableArray alloc] initWith…]. Hell, not quite.

[NSMutableArray arrayWith...] and other, similar factory methods, ‘emulate stack allocation’ for reference types. This means that we don’t need to worry about releasing them, as the so-called autorelease pool will take care of them for us.

When we check our code for memory issues, knowing which objects are kept in memory (on the heap) is essential. One way to learn about these is to scan for alloc, retain and release statements. The so called ‘shorthand forms’ allow using objects transiently, without worrying about memory issues, so this convention can help reduce the time spent on memory management.

There are downsides to this for unfortunate beginners:

(1) When we start with objective c, the [alloc[init form appears verbose and cumbersome. So we're likely to create our own shortcuts -- generating 'silent allocations' that make memory management harder.
(2) If we use the 'shorthand' forms, we quickly end up with weird, hard to fix bugs, because we might end up assigning auto-releaseable objects to variables, then these objects get deleted implicitly, and finally we end up accessing... ...garbage(!!!).

11. Beware of  abusing autorelease [NEW]

Autorelease is useful and in some cases you cannot avoid using it:

  • Objects returned by factory methods
    A(n essential) convention dictates that objects created using [alloc] have a reference count of 1. In contrast, callers of factory methods are not responsible for releasing returned objects unless they retain them (see #10)
    Since we can’t use [release] before returning an object we just created, we need to use [autorelease]
  • An object on the call stack may get deallocated if [release] is called.
    Now, it may be argued that only bad design can cause this to happen. Nevertheless one way to solve the problem (it can get nasty) is to use [autorelease]

Now that this is out of the way, beware of practices involving using [autorelease] as a ‘default safe way’. Here’s why:

If an object deallocates unexpectedly following a call to [autorelease] the call stack above [dealloc] doesn’t tell you what caused this object to deallocate.

I don’t see how a coding style involving loosing track of deallocation events can be safe.

12. You can crash the leaks tool in Instruments (seen in Instruments 4.0, 4.1) [NEW]

Recently I managed quirky memory management code that didn’t crash on device or in the simulator, yet crashed instruments. Checking the details, I stumbled on something like ‘invalid leaks data’.

I was about to use up one of my support tickets but reflected that sending my code over and waiting for the ticket to process would take a lot longer than reverting my changes and use the weak muscle to figure it out.

On the downside I got lucky before I managed to narrow it down.

Even if you’re not part of a team, consider using versioning (SVN or whatever new-fangled stuff you’d like).

Kind reminder:

No versioning
=> no diff tool
=> no way to accurately revert changes
=> panic
=> loss of money
=> loss of sleep
=> loss of hair(*)

(*)If you are bald I trust this won’t be an issue.

13. WTF my code crashes when ‘unplugged’ [NEW]

Consider the following case:

  • Your code doesn’t crash when debugging on-device.
  • Your code doesn’t crash when debugging in the simulator.
  • Your code crashes when running in the simulator after pressing the app icon.
  • Your code crashes on-device when running after pressing the app icon.

Then try this:

  • Disable NSZombieEnabled. Quite possibly you’ll see a fairly non-descript crash in the debugger when running the same code.
  • Try to isolate the stack that causes the crash (it’s not meant to be fun but using a dichotomy you might get it done in less than an hour)
  • Re-enable NSZombieEnabled. At this point you may see inconsistent variable assignments in the debug window.
  • Set breakpoints on [dealloc]. Quite possibly you’re deallocating an object that’s already ‘somewhere up’ on the call stack. On sunny days this crashes the device/simulator (hey, it’s actually a GOOD thing). On rainy days it drives the debugger crazy.

Build errors & warnings

14. Warning: Multiple Build Commands for output file …

In XCode, the name of a resource (e.g. a picture to include in the build as resource) is different from the path the resource is retrieved from. Several resources can have the same name, linked with different paths. So for example we can have:

  • foo.jpg (/images/foo.jpg)
  • foo.jpg (/mypics/draft/foo.jpg)

In the final bundle, however these resources are in conflict, they both target /foo.jpg. XCode will issue a warning if resources conflict in this way.

Unsurprisingly, this typically happens when reorganizing project resources.

15. Linking C++ libraries [NEW]

If your project depends on C++/ObjC++ libraries, you may need to add -lstdc++ to other linker flags to your build (see here).

Nibbling UIs (Interface Builder)

16. Action mappings are one-to-many

Yesterday I copied a button from my UI and bound an action to it. Then I was rather puzzled to find that, when I clicked on this button, my game started off with an ominous GL error code. I thought binding an action to a button overrides the previously bound action. It doesn’t. The same user action on the same widget can bind several IBAction targets. In my case this caused the game’s start method to be called twice.

Asset management

17. Use the blue folders [NEW]

If you have hundreds of assets, adding them manually will be a pain. However you can link a whole folder; in XCode’s ‘add files wizard’ select your folder and tick create folder references automatically…

XCode is getting better at detecting changed/added assets between builds (but see #18, below)

18. Sometimes you need to remove your app from the simulator/test device [NEW]

If your code relies on a mechanism allowing to retrieve a resource from one of several locations, you need to delete your app from the simulator / device whenever you remove assets from a blue folder.

Let’s say your sound folder is organized like this:

default_sounds/
---- KO_sound.caf
---- goblin_sounds/
-------- KO_sound.caf

Now suppose you deleted KO_sound.caf under goblin_sounds. Well the goblin specific sound recorded from your little sister’s performance will still load and play because it doesn’t get removed automatically.

Between builds, no files are deleted from package contents. I don’t know whether it’s a bug or not. It’s often annoying.

Don’t retain anything unless you must

Regarding reference counting, this is the idea I’d like a developer to at least consider. For several reasons.

  • A dangling pointer / weak reference needn’t be evil. During development hitting a dangling pointer is better than preventing an object to deallocate when it should. An object that exceeds it’s intended lifetime can behave in undesirable, unpredictable ways. All it takes to detect an invalid object is turning NSZombieEnabled on.
  • Everything retained needs to be released. Retain less = less work.
  • If the sums don’t add up (over-released/over-retained object) it’s easier to work out what’s wrong when the number of objects involved is small (e.g. 1, 2 or 3)
  • Potentially any object that retains a target will increase the target’s lifetime; this a priori translates into increased memory usage.
  • Whenever retaining an object we risk creating a cyclic reference. Of course ‘we know what we’re doing’ (and cyclic dependencies can be removed) but isn’t it just easier to avoid getting too many of these.

Unwanted objects that remain inside the runtime after they should have deallocated will harm you. The more your system is dynamic (e.g. game, simulation) the more these objects are likely to generate functional bugs that are hard to figure.

I read a little about automated reference counting (ARC) which we are getting in iOS5. If I understand correctly (reading here) the central idea of this article will translate to ‘don’t abuse strong references’. Now that I more or less get it I look forward to using ARC but I guess I’ll be waiting for another 6 months or so, being a happy laggard.

A quick introduction

Reference counting approaches memory management indirectly, using concurrent ownership:

  • Take ownership of an object by retaining it
  • Relinquish ownership by releasing the object.
  • When all owners of an object have released it, the object is deallocated.

indirect : we don’t explicitly deallocate the object.
concurrent: several objects can simultaneously retain the same target.

The basic rules are covered in many places, like here and here and from the horse’s mouth, here.

Reference counting is efficient, error prone and occasionally awkward.

More efficient than garbage collection: objects get deallocated as soon as their reference count reaches zero, whereas GC is heuristic and may cause your program to slow down unexpectedly while it’s doing its thing.

Error prone – programmers need to pair release/retain statements (either directly or indirectly). Mismatched statements cause a program to leak or crash. Additionally reference counting is hackable; it is easy to traffic the sums (either accidentally or by design) and obtain a valid program that handles memory correctly, while violating reference counting rules.

Awkward, notably when we know beforehand that we would like to deallocate a well defined subset of the runtime graph. A typical example is when you start a kind of ‘session’, allocate any number of objects in the course of the session and wish to deallocate all the objects at the end of the session. In such cases opting out may be somewhat short sighted yet remains attractive.

A design idea

There is a principle which I find rather productive: instead of thinking about whether an object should retain X or not, consider X then try to think about an object ‘up the runtime graph’ that should own X. Often there is an object Y such that, if Y deallocates, X should also deallocate. It could be the parent of X or maybe another object up the chain.

Now, if there is only one such object Y, then you don’t need to retain X anywhere else. You can even assert the retain count to ensure that X is unambiguously managed by Y.

Anti-patterns?

There are little recipes around (e.g. here and here) that you can use to ‘ease the pain of memory management’.  From the point of ownership these recipes work the same way GC does: easy way out of memory management issues, hard into functional bugs with all the enticing prospects of a muddle-through approach.

One point these approaches have in common is ‘if in doubt, retain’. I’m OK with that as long as I know (beyond reasonable doubt) that keeping the target alive won’t generate unwanted behavior. If the target is an observer that receives and processes notifications… …then if in doubt, don’t retain. A clean, happy crash will provide the decision point where you can say:

  • ‘Yea, this object should still be alive at this point’ (in which case maybe something else should have retained it) or…
  • ‘No, this object is dead and well dead, we should have sent a death note’

Additionally these approaches look incomplete. You need to use class extensions if you want to declare everything as a property without exposing all your ivars.

Weak references

An unretained field is a ‘weak reference’. At least in a first approach, the use of weak references is encouraged in a number of situations:

  • Backward references from a child to a parent
  • Listener sets. See a straightforward application here.
  • Same type objects cross-referencing each other.
  • Any situation where you feel unsure whether to claim ownership (retain) or not.

Implementation details

Maybe for historical reasons there are two approaches to enforcing reference counting in objective C:

  • The non intrusive approach revolves around tagging using properties and indirect access using self.x = . Although this approach looks theoretically better and safer there are practical details of how it is done in Objective C which I often find off-putting. For one I like to not declare properties until I want to expose public state, and I’m not used to class extensions, thus find myself unwilling to add class extensions to my .m files.
  • An older approach revolves around the [release] and [retain] statements. The advantage (easier reviewing/debugging) and inconvenience (intrusive approach leading to somewhat cluttered code) are the explicit way in which things are done. This leads to a weird situation because it makes it more likely that bugs are introduced while making the same bugs easier to fix.

Note about [autorelease]

[autorelease] is very convenient and helps avoid errors in many situations. Sadly enough when an error does occur and [autorelease] is the lucky guy that causes a target to deallocate, we get very little debugging information because [autorelease] doesn’t take effect until we exit the frame.

So I try to limit its usage to where it’s unavoidable.

What is covered elsewhere (or should be)

  • Cocoa collections (NSArray, NSSet, NSDictionary) retain all their elements. This can be a hindrance in some cases, but you can configure the underlying, toll-free bridged counterparts, as demonstrated here.
  • There are various approaches to notifying stakeholders when an object gets deallocated. I will try to write a quick article about an approach I find useful when implementing observer schemes.

Activity log

  • Last weekend (June 21st) I was very busy working on fixing memory leaks in my apps. I’d profiled the product  using ObjectAlloc before, that doesn’t really help fixing leaks per se, but it does help making sure that the app doesn’t run out of memory.
    So why I am fixing the leaks? I’m not sure. For a while I was just worried my app might get rejected because of having so many leaks. But then I’m an either/or person at times. Either fix all of the leaks I can find, or don’t fix any.
    Yea. Now you’re asking why I need to think whether I should fix leaks or not? Well, when you’re in a genuine multitasking environment and your app is running for a long long time, you have to fix the leaks. If you’re writing a game and it can already run for 4 times the expected maximum playtime, in my humble opinion you’re just trying to make your game crash and wasting your time by fixing something that already works .

    That is exactly what I’ve been doing.

  • A side effect of fixing leaks is over-releasing memory. Unfortunately, while leaks don’t do much harm except killing memory over time, over-releasing causes random crashes.
    TIP: right click on your executable in the project browser; select get info and choose the Arguments tab. add the following environment variable: NSZombieEnabled and set its value to YES. That will help you with zombies (if you don’t know  what that is, search NSZombieEnabled. This will help you fix random crashes.
  • This week I got busy getting an artist to help me with promotional material, not the least, my app icon. Can’t wait to see what she’s up to.
  • This week-end I’ve been internationalizing my app.

Babelize?

Earth doesn’t speak English

I’ve got about 2000 words worth of dialogues and other text bits. Not counting the app store blurb.
I’m planning on localizing in French, Chinese and Japanese (sure, english is the default). So I got into the plist xml format.
I read a post somewhere which seems to indicate you get 50% extra sales when localizing to French. So I guess translation is worth it.

Translators don’t speak XML

Humanly readable? I doubt; in my previous company programmers ended doing the translation and, retrospectively that may have been a reasonable (albeit expensive and somehow despicable) choice. XML is not quite humanly readable.

So I extracted all the text and made it look like a movie script. Then I wrote a java parser to read the script and re-write it as plist-xml, topping all that with a translation component wrapping the plist.

Does this room understand Chinese?

Boring stuff if you ask me, but seems it’s well worth it:

  • Test driving the system, the translator made only 4 mistakes, accidentally deleting a colon here and there. I could fix the mistakes in minutes.
  • Having the dialogs hard-wired in the game code was OK. For drafting stuff it’s kind of fast. But having them removed from the game code not just clarifies stuff, it also helps me normalize talk-back occurrences (picking an item, sighting an important NPC etc…)
  • It’s OK for translators to edit the text using about anything. Interestingly, we can even use word (or whatever word processor) to protect the text that shouldn’t be translated. Then paste everything back in a plain text editor, feed it into the parser and enjoy

My internet is snailing again. So I’ll provide references about all this stuff later.