Advertise Mobile SDKs Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

Interface 2, Advanced iOS
Mockup & Code Gen
($9.99)

Make your own iPhone apps
and run them live!
(free)

Pic Frame Dynamo: Photo Editing
($0.99)

Abiliator
($1.99)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Development

Reply
 
LinkBack Thread Tools Display Modes
Old 04-03-2009, 05:34 PM   #1 (permalink)
jsd
at this moment
 
Join Date: Mar 2009
Location: San Francisco, CA
Posts: 900
jsd is on a distinguished road
Default memory management confusion

I've got a function that queries a webservice for some JSON which is turned into a NSDictionary. I want to return one of the dictionary entries, which is an NSArray. I'm doing something wrong with the whole retain/release business because the app crashes when trying to access the array - but only every other time I run it.

The method definition is
Code:
- (NSArray *) getRecentMomentsForUser
The end of the method is:

Code:
 	NSDictionary *dictionary = [[CJSONDeserializer deserializer] deserializeAsDictionary:jsonData error:nil];
	NSArray *ret = [[NSArray alloc] init];
	ret = [dictionary objectForKey:@"four_up"];
	return ret;
The code that makes use of it looks like this:

Code:
- (void)viewDidLoad {
	tmWeb *web = [[tmWeb alloc] init];
	NSArray *array = [web getRecentMomentsForUser];
	self.listData = array;
	[web release];
}
jsd is offline   Reply With Quote
Old 04-03-2009, 07:37 PM   #2 (permalink)
Registered Member
 
Join Date: Nov 2008
Posts: 188
jsonli is on a distinguished road
Default

You create an NSArray, but the reference is lost when you reassign ret to temporary value from CJSONDeserializer.

So two problems, you are leaking the NSArray you declare, and you do not retain the temporary value.
jsonli is offline   Reply With Quote
Old 04-03-2009, 10:26 PM   #3 (permalink)
jsd
at this moment
 
Join Date: Mar 2009
Location: San Francisco, CA
Posts: 900
jsd is on a distinguished road
Default

Quote:
Originally Posted by jsonli View Post
You create an NSArray, but the reference is lost when you reassign ret to temporary value from CJSONDeserializer.

So two problems, you are leaking the NSArray you declare, and you do not retain the temporary value.
i changed the end of the method to
Code:
NSArray *ret = [[dictionary objectForKey:@"four_up"] retain];
return ret;
but i'm still having the crash-every-other-run problem. where else should i be looking for problems?
jsd is offline   Reply With Quote
Old 04-03-2009, 10:28 PM   #4 (permalink)
Registered Member
 
Join Date: Nov 2008
Posts: 188
jsonli is on a distinguished road
Default

Quote:
Originally Posted by jsd View Post
i changed the end of the method to
Code:
NSArray *ret = [[dictionary objectForKey:@"four_up"] retain];
return ret;
but i'm still having the crash-every-other-run problem. where else should i be looking for problems?
Are you familiar with the Cocoa Memory Management rules? Your app will be haphazard if you haven't mastered the principles.
jsonli is offline   Reply With Quote
Old 04-03-2009, 11:20 PM   #5 (permalink)
jsd
at this moment
 
Join Date: Mar 2009
Location: San Francisco, CA
Posts: 900
jsd is on a distinguished road
Default

Quote:
Originally Posted by jsonli View Post
Are you familiar with the Cocoa Memory Management rules? Your app will be haphazard if you haven't mastered the principles.
I'm trying to learn but it honestly doesn't make any sense to me right now. I haven't dealt with anything this low level since 6502 assembler in the 80's. Mostly I've been doing php and perl which manage memory for you.

All I know is I have a Dictionary and I want to return a pointer to something within that dictionary. Do I retain it? Seems like yes, since I want the pointer to point to valid stuff... But if I retain it, how will it ever get freed? It seems crazy to have the function on the other end deal with releasing it. But maybe that's right? I dunno... it hasn't "clicked" yet.
jsd is offline   Reply With Quote
Old 04-03-2009, 11:29 PM   #6 (permalink)
New Member
 
Join Date: Mar 2009
Posts: 77
shonday is on a distinguished road
Default

You can either use the convenience method or you can alloc it yourself and then when you return it autorelease it. If you use the convenience method you need to claim ownership of it to ensure it doesn't get released without you knowing. For instance,

NSArray *ret = [[NSArray alloc] initWithArray:[dictionary objectForKey:@"four_up"]];
return [ret autorelease];

or even

return [[[NSArray alloc] initWithArray:[dictionary objectForKey:@"four_up"] autorelease];

Muahahaha.

You need to read up on Memory Management. If you use alloc, new, or copy, then you must release or autorelease it at some point. If you use something like arrayWithArray, it's taken care of for you. It's confusing, I admit. I probably made a mistake.

Last edited by shonday; 04-04-2009 at 12:25 AM.
shonday is offline   Reply With Quote
Old 04-04-2009, 01:04 PM   #7 (permalink)
Registered Member
 
Join Date: Nov 2008
Posts: 188
jsonli is on a distinguished road
Default

Quote:
Originally Posted by jsd View Post
I'm trying to learn but it honestly doesn't make any sense to me right now. I haven't dealt with anything this low level since 6502 assembler in the 80's. Mostly I've been doing php and perl which manage memory for you.

All I know is I have a Dictionary and I want to return a pointer to something within that dictionary. Do I retain it? Seems like yes, since I want the pointer to point to valid stuff... But if I retain it, how will it ever get freed? It seems crazy to have the function on the other end deal with releasing it. But maybe that's right? I dunno... it hasn't "clicked" yet.
You are absolutely correct that it is wack to release it from another method and to have some implicit contract like that.

Anytime you use "alloc", you have allocated memory, and the rules state that since you allocated, *you* are responsibile for deallocating (i.e. releasing) at some point.

Pretty shortly though, you'll realize the problem you had, where you allocate memory, but you need that value to exist for the next method, so you cannot call "release".

That's where autorelease comes into play. If you call autorelease on something you have just allocated, the value is valid for the remainder of the life of the callstack essentially, and only when it is done is the value released.

So essentially you can pass that value around from method to method in a chain of method calls and returns, and it remains valid until the chain has ended.

And since the value is released, you have fulfilled your responsibility of releasing the memory at some point.

On the other side of the equation, if you obtain a value from some object or class without "alloc" then consider it a temporary value that will only exist for the life of the callstack. If you need it to exist for longer than this, whatever needs that value should call retain on it. But by calling retain, it should also call release at some point, so there are no leaks.

It makes sense to design your software so that the entity that needs the value to stick around as more than a temporary value calls retain. You'll see that the NS framework is written like this as well. For example, an NSArray will retain its contents itself, and you do not need to call retain on each individual element you have added to the array.
jsonli is offline   Reply With Quote
Old 04-04-2009, 01:11 PM   #8 (permalink)
Registered Member
 
Join Date: Sep 2008
Posts: 180
ipodtouchmaster05 is on a distinguished road
Default

You should be able to do this:
Code:
NSDictionary *dictionary = [[CJSONDeserializer deserializer] deserializeAsDictionary:jsonData error:nil];
	NSArray *ret = [dictionary objectForKey:@"four_up"];
	return [ret retain];
ret will now be retained, so have this in your viewDidLoad:
Code:
- (void)viewDidLoad {
	tmWeb *web = [[tmWeb alloc] init];
	NSArray *array = [web getRecentMomentsForUser];
	self.listData = array;
        [array release]
	[web release];
}
__________________
FingerTest: Fun game where you put your fingers to the ultimate test! [AppStore] - $0.99
Penguins!: Addictive game. [AppStore] - $1.99
MTracker: Easy to use money tracker. [AppStore] - $0.99
iBubblePop: Try to pop as many bubbles as you can![AppStore] - $1.99

If you would like me to work on a project for you, contact me at the following email address.
madpike05@aol.com
ipodtouchmaster05 is offline   Reply With Quote
Old 04-04-2009, 01:14 PM   #9 (permalink)
Registered Member
 
Join Date: Nov 2008
Posts: 188
jsonli is on a distinguished road
Default

Quote:
Originally Posted by ipodtouchmaster05 View Post
You should be able to do this:
Code:
NSDictionary *dictionary = [[CJSONDeserializer deserializer] deserializeAsDictionary:jsonData error:nil];
	NSArray *ret = [dictionary objectForKey:@"four_up"];
	return [ret retain];
ret will now be retained, so have this in your viewDidLoad:
Code:
- (void)viewDidLoad {
	tmWeb *web = [[tmWeb alloc] init];
	NSArray *array = [web getRecentMomentsForUser];
	self.listData = array;
        [array release]
	[web release];
}
That creates a coupling between the returning method and any method that uses that value though. The person calling will have to always remember to release that value even though they never retained.

By the rules, the caller should retain if they need the value, if not, the value will simply expire, and no one needs to assume anything.
jsonli is offline   Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



» Advertisements
» Online Users: 330
6 members and 324 guests
blueorb, guusleijsten, Kryckter, LEARN2MAKE, n00b, SLIC
Most users ever online was 1,387, 04-10-2012 at 04:21 AM.
» Stats
Members: 175,649
Threads: 94,113
Posts: 402,880
Top Poster: BrianSlick (7,990)
Welcome to our newest member, Anwerbl
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 08:54 PM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.0