Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 545 Vote(s) - 3.58 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Understanding reference counting with Cocoa and Objective-C

#11
Let's start with `retain` and `release`; `autorelease` is really just a special case once you understand the basic concepts.

In Cocoa, each object keeps track of how many times it is being referenced (specifically, the `NSObject` base class implements this). By calling `retain` on an object, you are telling it that you want to up its reference count by one. By calling `release`, you tell the object you are letting go of it, and its reference count is decremented. If, after calling `release`, the reference count is now zero, then that object's memory is freed by the system.

The basic way this differs from `malloc` and `free` is that any given object doesn't need to worry about other parts of the system crashing because you've freed memory they were using. Assuming everyone is playing along and retaining/releasing according to the rules, when one piece of code retains and then releases the object, any other piece of code also referencing the object will be unaffected.

What can sometimes be confusing is knowing the circumstances under which you should call `retain` and `release`. My general rule of thumb is that if I want to hang on to an object for some length of time (if it's a member variable in a class, for instance), then I need to make sure the object's reference count knows about me. As described above, an object's reference count is incremented by calling `retain`. By convention, it is also incremented (set to 1, really) when the object is created with an "init" method. In either of these cases, it is my responsibility to call `release` on the object when I'm done with it. If I don't, there will be a memory leak.

Example of object creation:

NSString* s = [[NSString alloc] init]; // Ref count is 1
[s retain]; // Ref count is 2 - silly
// to do this after init
[s release]; // Ref count is back to 1
[s release]; // Ref count is 0, object is freed


Now for `autorelease`. Autorelease is used as a convenient (and sometimes necessary) way to tell the system to free this object up after a little while. From a plumbing perspective, when `autorelease` is called, the current thread's `NSAutoreleasePool` is alerted of the call. The `NSAutoreleasePool` now knows that once it gets an opportunity (after the current iteration of the event loop), it can call `release` on the object. From our perspective as programmers, it takes care of calling `release` for us, so we don't have to (and in fact, we shouldn't).

What's important to note is that (again, by convention) all object creation *class* methods return an autoreleased object. For example, in the following example, the variable "s" has a reference count of 1, but after the event loop completes, it will be destroyed.

NSString* s = [NSString stringWithString:@"Hello World"];

If you want to hang onto that string, you'd need to call `retain` explicitly, and then explicitly `release` it when you're done.

Consider the following (very contrived) bit of code, and you'll see a situation where `autorelease` is required:

- (NSString*)createHelloWorldString
{
NSString* s = [[NSString alloc] initWithString:@"Hello World"];

// Now what? We want to return s, but we've upped its reference count.
// The caller shouldn't be responsible for releasing it, since we're the
// ones that created it. If we call release, however, the reference
// count will hit zero and bad memory will be returned to the caller.
// The answer is to call autorelease before returning the string. By
// explicitly calling autorelease, we pass the responsibility for
// releasing the string on to the thread's NSAutoreleasePool, which will
// happen at some later time. The consequence is that the returned string
// will still be valid for the caller of this function.
return [s autorelease];
}

I realize all of this is a bit confusing - at some point, though, it will click. Here are a few references to get you going:

- [Apple's introduction][1] to memory management.
- [Cocoa Programming for Mac OS X (4th Edition)][2], by Aaron Hillegas - a very well written book with lots of great examples. It reads like a tutorial.
- If you're truly diving in, you could head to [Big Nerd Ranch][3]. This is a training facility run by Aaron Hillegas - the author of the book mentioned above. I attended the Intro to Cocoa course there several years ago, and it was a great way to learn.


[1]:

[To see links please register here]

"Apple's introduction to Cocoa's memory management"
[2]:

[To see links please register here]

[3]:

[To see links please register here]

"Big Nerd Ranch"
Reply

#12
I'll not add to the specific of retain/release other than you might want to think about dropping $50 and getting the Hillegass book, but I would strongly suggest getting into using the Instruments tools very early in the development of your application (even your first one!). To do so, Run->Start with performance tools. I'd start with Leaks which is just one of many of the instruments available but will help to show you when you've forgot to release. It's quit daunting how much information you'll be presented with. But check out this tutorial to get up and going fast:
[COCOA TUTORIAL: FIXING MEMORY LEAKS WITH INSTRUMENTS](

[To see links please register here]

)

Actually trying to *force* leaks might be a better way of, in turn, learning how to prevent them! Good luck ;)
Reply

#13
My usual collection of Cocoa memory management articles:

[cocoa memory management][1]


[1]:

[To see links please register here]

Reply

#14
NilObject's answer is a good start. Here's some supplemental info pertaining to manual memory management (*required on the iPhone*).

If you personally `alloc/init` an object, it comes with a reference count of 1. You are responsible for cleaning up after it when it's no longer needed, either by calling `[foo release]` or `[foo autorelease]`. release cleans it up right away, whereas autorelease adds the object to the autorelease pool, which will automatically release it at a later time.

autorelease is primarily for when you have a method that needs to return the object in question (*so you can't manually release it, else you'll be returning a nil object*) but you don't want to hold on to it, either.

If you acquire an object where you did not call alloc/init to get it -- for example:

foo = [NSString stringWithString:@"hello"];

but you want to hang on to this object, you need to call [foo retain]. Otherwise, it's possible it will get `autoreleased` and you'll be holding on to a nil reference *(as it would in the above `stringWithString` example*). When you no longer need it, call `[foo release]`.
Reply

#15
If you understand the process of retain/release then there are two golden rules that are "duh" obvious to established Cocoa programmers, but unfortunately are rarely spelled out this clearly for newcomers.

1. If a function which returns an object has `alloc`, `create` or `copy` in its name then the object is yours. You must call `[object release]` when you are finished with it. Or `CFRelease(object)`, if it's a Core-Foundation object.

2. If it does NOT have one of these words in its name then the object belongs to someone else. You must call `[object retain]` if you wish to keep the object after the end of your function.

You would be well served to also follow this convention in functions you create yourself.

(Nitpickers: Yes, there are unfortunately a few API calls that are exceptions to these rules but they are rare).
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through