allocating/releasing memory management query

0 views
Skip to first unread message

Byron

unread,
Mar 6, 2010, 5:46:00 PM3/6/10
to iPhone Application Development Auditors
As i have been following lessons, i have noticed something that i am
finding difficultly to understand and find the answer to.. please bear
in mind i am currently researching more into memory management.

Say i create a Person class and within a different class header file i
create a person instance as follows:

Person *barry;
@property (nonatomic, retain) Person *barry;

now within the implementation files init method, i have noticed the
following being done to instantiate the instance:

Person* p = [[Person alloc]init];
self.barry = p;
[p release];

and in dealloc method a release being called.. Now My question is can
i not simply do the following in my init method instead?

barry = [[Person alloc]init];

why is instance created.. assigned to "barry" then released?

Many Thanks
By

redbirdo

unread,
Mar 7, 2010, 9:37:13 AM3/7/10
to iPhone Application Development Auditors
The reason is that your property 'Person *barry' is set up with the
'retain' keyword. This means that the generated setter will call
retain on the value passed in (it also calls release on the previous
value, if there is one). The line 'self.barry = p' results in a call
to the generated setter method with the value 'p'. This means that 'p'
will end up with a retain count of 2 if you don't maintain a reference
to it and release it after the assignment.

Vicki

bluelobe

unread,
Mar 7, 2010, 11:57:30 AM3/7/10
to iPhone Application Development Auditors
This is my understanding:

1. when you do...

@property (nonatomic, retain) Person *barry;

you 'retain' so you must release, thus in your implementation's
dealloc you balance this out:

- (void) dealloc {
[barry release];
[super dealloc];
}

2. if you do...

barry = [[Person alloc] init];

...you used alloc, so aside from the [barry release]; at your dealloc,
you need another [barry release]; but what if you need to use barry in
your code, when will you add the [barry release]? So, if you used...

Person* p = [[Person alloc]init];
self.barry = p;
[p release];

...you don't have to worry about doing a [barry release]; since you
did not alloc or retain another instance of barry. All you did was
alloc 'p' which you have now released and thus don't have to worry
about.

Byron

unread,
Mar 8, 2010, 12:01:13 PM3/8/10
to iPhone Application Development Auditors
Thanks for the replies.. much appreciated. I am still a little
confused about the assign attribute.. as you have mentioned retain
will increment the retain count by one.. so a release is needed to
balance the call. This is what i have been reading for memory
management.

Although the only thing i can find on the default for properties
"assign" is that that it is a simple assignment and that it is
typically used for scalar types.

So an int or float can simply be assigned? but if i was to use assign
for a class instance would this not be the "best" way to manage
memory?

i shall give an example:

@interface College: NSObject {
int students;
NSString *collegeName;
Person *barry;
Person *sally;
}

@property (assign)int students;
@property (assign)NSString *collegeName;
@property (nonatomic, retain)Person *barry;
@property (nonatomic, retain)Person *sally;

@implementation College {

-(id)init {
if (self = [super init]) {
self.students = 187;
self.collegeName = [NSString
stringWithFormat:@"barrySixthForm"];
Person *p = [[Person alloc]init];


self.barry = p;
[p release];

self.sally = [Person init];
}
return self;
}

-(void)dealloc {
[students release];
[collegeName release];
[barry release];
[sally release];
[super dealloc];
}

}

is this correct? can i still use assign collegeName or should i use
retain? and when i set sally in the init method i dont use alloc so
the retain count stays at one and is set to 0 when i release in the
dealloc method.

Any feedback would be great

Thanks again
Byron

Byron

unread,
Mar 8, 2010, 12:07:58 PM3/8/10
to iPhone Application Development Auditors
oh.. and the nonatomic part.. am i right in saying this is used if you
don't want to put a lock on the getter method when synthesising? so
that multiple threads can access the ivar at once?

bluelobe

unread,
Mar 8, 2010, 2:40:28 PM3/8/10
to iPhone Application Development Auditors
here's a useful list for using @property:

for C types like int, float, char, etc. use "assign"
for Objects that don't need setters/getters, use "readonly"
for NSString, you can use "copy"
for all the rest, use "retain"

"nonatomic" is used when you're not using threading (which as
beginning developers we rarely if ever use) in your iPhone app--to
speed up processing.

redbirdo

unread,
Mar 8, 2010, 3:55:46 PM3/8/10
to iPhone Application Development Auditors
Byron,

Regarding your query on using assign / retain / copy for properties...

The very helpful list given by bluelobe tells you when you should
typically use them although you may still be confused as to WHY you
should not use assign for object properties.

This relates to some fundamental programming concepts of primitive and
pointer data types. Someone else would probably be able to explain
this better but I'll have a stab at it.

Basically, if you think of a variable as an address in memory, then
for primitive types the content of that address is the actual value,
whereas for pointer types the content of that address points to
another chunk of memory containing the object data. This means that if
you make an assigment between two primitive types the actual value is
copied from one variable (address) to the other. If you make an
assignment between two pointer types only the object's address is
copied from one variable to the other, both variables are then
pointing to the same object data. If one of those variables then
releases that object and the other has not retained it the object will
be destroyed. As the properties of a class effectively represent its
internal state, it is very important that they don't get destroyed
until the class no longer needs them. Therefore all properties which
are pointers must either be copied (so the class owns them) or
retained (so they will not be destroyed until the class releases
them).

Hope that makes some sort of sense.

Vicki

Byron

unread,
Mar 8, 2010, 4:46:26 PM3/8/10
to iPhone Application Development Auditors
thanks, that has helped loads.. i am still reading up on it and
looking at examples. so slowly getting to grips with it all, if assign
is used do i still need to release in my dealloc method because it
doesn't increment the retain count? i have seen people doing the
following instead:

ivarName = nil;

Thanks again for your time
Byron

Georges-Henry Portefait

unread,
Mar 8, 2010, 6:01:44 PM3/8/10
to iphone-appd...@googlegroups.com
Hi ,

I am maybe not the most qualified to answer .. but I will try my
0.02€ ;)

Even if you do not have to release something, it is good practice to
set the pointer back to nil once you finish using it.
This way if you place a call later (which is an error BTW) due to the
graceful fail of sending a message to nil in Objective-C, nothing will
happen.

Moreover when we will get GC on iPhones :) I guess that as you are not
pointing to this object anymore it will get deallocated.

I hope all the above are correct ;)

Enjoy Cocoa coding ;)

Best regards

Chewbee

> --
> You received this message because you are subscribed to the Google
> Groups "iPhone Application Development Auditors" group.
> To post to this group, send email to iphone-appd...@googlegroups.com
> .
> To unsubscribe from this group, send email to iphone-appdev-aud...@googlegroups.com
> .
> For more options, visit this group at http://groups.google.com/group/iphone-appdev-auditors?hl=en
> .
>

Richard Nerf

unread,
Mar 8, 2010, 8:55:11 PM3/8/10
to iphone-appd...@googlegroups.com
I haven't checked this out, but my interpretation of on the set-to-nil
idiom is:

obj.ivar = nil;

The setter releases the current value of the ivar (equivalent to [ivar
release])
It sets the value to nil;
it does [ivar retain} on nil, which is OK...

Wayne

unread,
Mar 8, 2010, 11:29:13 PM3/8/10
to iPhone Application Development Auditors
Barry,

I will attempt to answer your question. Before I do, please check out
the tools from the Run menu in Xcode, specifically the ones in Run
With Performance Tool, you will find an option called Leaks and one
called Object Allocator. If nothing else they have some nice
graphs :-)

Here is how I think of it:

An alloc = 1 on the retain count
A retain = +1 on the retain count.
A release = -1 on the retain count.
An assign = 0 on the retain count (i.e. no change)

So if you have the person Barry who you said should be retained as per
the property definition, we can walk through it as follows

Person *barry;


@property (nonatomic, retain) Person *barry;

Whoever barry is instantiated as it will automatically have a retain
count of +1. Since barry has not been instantiated at this point, you
*do not* have to release barry, i.e. you only have to if you choose to
instantiate an object and let barry point to it.

In your code you go ahead and instantiate an object and let barry
point to it:

Person* p = [[Person alloc]init];
self.barry = p;
[p release];

In the above code you alloc memory for Person p, let barry point to it
and release Person p. To walk through it p = a Person and because its
an alloc gets a retain count of 1. When you point barry to the same
Person, barry gets a retain count of 2, because you said barry should
retain whatever it points it (refer to the property def. of barry).
Then you said lets release the object that p points to which makes
it's retain count be 0 for pointer p and 1 for pointer barry.

At this point you must release barry at some point in your
application, typically done in the dealloc method, though you could
release barry at another part of the application (i.e. viewDidUnload)
and have it work fine.

As pointed out earlier the case with assign, is that if you set the
pointer to nil you *are* releasing the memory. An example:

Barry assigned to object X
(another pointer) Mannilow assigned to object X

you say you want Barry to point to nil, i.e. object X is now nil. Now
mannilow is also nil, and if you, like I seem to do way too often, try
to ask Mannilow something you crash :-)

I hope this helps, this is my understanding and it is entirely
possible I have it wrong, if so please tell me what I've missed.

Best,
Wayne

P.S. It was coincidence that in my first "real" job one of my
coworkers dubbed me "crash", he dubbed himself "burn" as the two of us
could take out a server in under 5 mins with our buggy code :-)

P.S.S. Thank you all for this group, without it I would have never
completed Paparazzi 2.

> >> For more options, visit this group athttp://groups.google.com/group/iphone-appdev-auditors?hl=en

redbirdo

unread,
Mar 9, 2010, 4:47:45 AM3/9/10
to iPhone Application Development Auditors
>thanks, that has helped loads.. i am still reading up on it and
>looking at examples. so slowly getting to grips with it all, if assign
>is used do i still need to release in my dealloc method because it
>doesn't increment the retain count? i have seen people doing the
>following instead:
>
>ivarName = nil;

As you should only be using assign with primitive data types, not only
do you not need to release them but you can't call release on them
because they're not (pointers to) objects.

I must admit, I can't see why anyone would do this in a dealloc method
rather than a direct release. I thinks its a mistake. It wouldn't
cause a problem - it would still work but I can't see the point. Once
you're in dealloc, your object is being destroyed so you may as well
release its properties directly without any additional performance
overhead.

However, there is a method in ViewController in which you are
*supposed* to take this approach.

If you create a new UIViewController subclass via file->new, you will
see this generated method:

- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}

As the view can be re-loaded, it is not sufficient just to call
release from this method, you need to assign to nil to ensure myOutlet
is not still pointing to some random bit of dealloc'd memory which
could cause problems when the view is re-loaded. If the value is set
to nil you can test it to determine if you need to initialise it. Note
- if myOutlet were not set up as a (retained) property it would not be
released and there would be a leak.

You could choose to use a similar approach where appropriate in order
to keep your memory usage down.

Vicki

Byron

unread,
Mar 9, 2010, 7:40:20 AM3/9/10
to iPhone Application Development Auditors
Thank you everyone for all your help and guidance, it has helped me
throughly. I now understand the uses of retain etc due to your great
explanations, thanks again for all your help.

byron

Lenny Teng

unread,
Mar 9, 2010, 11:42:02 AM3/9/10
to iphone-appd...@googlegroups.com
If I may I'd like to ask a follow-up question a bit off topic, but still relates to allocating memory.  I just finished lecture 12 and in the 17:34 mark Alan is demo'ing web views and types the following lines of code:

NSURL *url = [NSURL URLWithString:textField.text];
NSURLRequest *request = [NSURLRequest requestWithURL:url];

And then says, "If I was a good programmer, instead of using these convenience methods I would do alloc/init and then dealloc, but today we're just going to do this."

So, is it bad to use convenience methods or should I always use alloc/init?  I been happily using convenience methods in my assignments thinking it was ok (mainly because I saw the instructors doing it all the time in the demos) and it's definitely much more, well, convenient.  Can someone shed some light when it might be ok to use convenience methods and when I must alloc/init?

Thanks,
Lenny


From: Byron <byron...@googlemail.com>
To: iPhone Application Development Auditors <iphone-appd...@googlegroups.com>
Sent: Tue, March 9, 2010 7:40:20 AM
Subject: [iPhone-AppDev-Auditors] Re: allocating/releasing memory management query
--
You received this message because you are subscribed to the Google Groups "iPhone Application Development Auditors" group.
To post to this group, send email to iphone-appd...@googlegroups.com.
To unsubscribe from this group, send email to iphone-appdev-auditors+unsub...@googlegroups.com.

redbirdo

unread,
Mar 9, 2010, 12:08:00 PM3/9/10
to iPhone Application Development Auditors
Lenny

As I understand it, it is considered good practice to avoid using the
convenience methods in order to keep the application's memory usage
down.

When we use convenience methods the objects returned are auto-released
'later'. From what I can gather, this is at the end of the current
event loop. I guess this makes sense as otherwise something might get
released whilst we were still using it! This means if we use
convenience methods all the time and have lots of temporary data we
could use a fair bit of memory before anything gets released.

I think I read some guidelines about this somewhere but can't remember
where offhand. I'll have to go digging...

I guess for a very small, memory light app it may not matter? (unless
they start letting us multitask with other apps more than they do at
the moment...)

Vicki

bluelobe

unread,
Mar 9, 2010, 2:13:59 PM3/9/10
to iPhone Application Development Auditors
Wayne,

Not wanting to belabor the point but, according to lecture 3 (Winter
2010 at around 48:00), using...

@property (nonatomic, retain) Person *barry;

...means the ff:

- (void)setBarry:(Person *)newBarry {
if (barry != newBarry) {
[barry release];
barry = [newBarry retain];
// barry’s retain count has been bumped up by 1
}
}

while using...

@property (nonatomic, copy) Person *barry;

...means the ff:

- (void)setBarry:(Person *)newBarry {
if (barry != newBarry) {
[barry release];
barry = [newBarry copy];
}
}

On the other hand, using...

@property (nonatomic, assign) means...

- (void)setBarry:(Person *)newBarry {
if (barry != newBarry) {
barry = newBarry;
}
}

So, if Byron did this:

barry = [[Person alloc]init]; or more correctly...

self.barry = [[Person alloc] init];

...or in non-dot notation...

[self setBarry:[[Person alloc] init]];

...it would mean barry will get a retain count of 2: alloc + retain =
2 because:

- (void)setBarry:(Person *)newBarry {
if (barry != newBarry) {
[barry release];
barry = [ [[Person alloc] init] retain]; // alloc is 1, then retain
adds another 1
}
}

which means, Byron akwardly has to do a [barry relase] (aside from the
one in dealloc) to avoid memory leaks. To avoid this mess, one should
do the usual:

Person *p = [[Person alloc] init];

bluelobe

unread,
Mar 9, 2010, 2:26:39 PM3/9/10
to iPhone Application Development Auditors
Byron,

By the way, doing this...

barry = [[Person alloc]init];

...is not the same as doing this...

self.barry = [[Person alloc]init];

In the first example, you're assigning barry directly. In the second
example, you're calling "setBarry":

1) barry = [[Person alloc] init];
2) [self setBarry:[[Person alloc] init]];

...again from Lecture 3 around 52:00

Scott Reynolds

unread,
Mar 9, 2010, 2:36:02 PM3/9/10
to iphone-appd...@googlegroups.com
I wasn't especially struggling with this issue, but neither was it completely clear to me. Thanks for the concise example!

--scott

Byron

unread,
Mar 16, 2010, 10:58:22 AM3/16/10
to iPhone Application Development Auditors
Sorry to bring this subject up again.. i have been writing programs
fine now but today i noticed in some sample code i was using that no
property had been assigned to a NSArray and everything worked fine.
does it simply create an autorelease object or is there actually a
leak?

in the .h file it literally has NSArray *array.. then when it is used
in the .m its something like this :

array = [NSArray arrayWithObjects:one,two,three,nil];

[self someMethodWithArray:array];

that is all.. what is happening here exactly?

Thanks in advance
Byron

> > iphone-appdev-aud...@googlegroups.com<iphone-appdev-auditors% 2Bunsu...@googlegroups.com>

redbirdo

unread,
Mar 16, 2010, 11:45:04 AM3/16/10
to iPhone Application Development Auditors
The NSArray arrayWithObjects method does not have the word alloc/init/
copy in it and therefore it returns a new autoreleased instance of
NSArray. If you need to keep a reference to it you need to retain it
(or assign it to a retained property). If you don't need it beyond the
end of the method, you can just use it and leave it to be
autoreleased.

Vicki

Reply all
Reply to author
Forward
0 new messages