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

Mockup & CodeGen, iPhone & iPad
($9.99)

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

Manu
($0.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 12-23-2009, 12:09 PM   #1 (permalink)
Divine avenger
 
Johanovski's Avatar
 
Join Date: Nov 2009
Location: Vic, Catalunya (Spain)
Posts: 320
Exclamation Release isn't working! The end of the world is here!

Repent, heretic! ^_^

Release is not doing what it's supposed to! I was happily working on my game when suddenly I've decided to watch how allocations are going on the device after making some changes at the images (avoiding .png image compression) and then, bang! The whole world crashed when I saw live memory is increasing as ever done. After seeking some explanation to the problem I've taken a memory printing function to see where exactly the problem is, and what a surprise when I saw that releasing functions are not freeing any space!

There are lot of images in the game so I've decided to load just the images that are going to be used and free useless images, then loading again when needed, etc.

I'm going to show you how all this works:

************************************************** ********
// First of all, the memory printing function:
- (void) print_free_memory {
mach_port_t host_port;
mach_msg_type_number_t host_size;
vm_size_t pagesize;

host_port = mach_host_self();
host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
host_page_size(host_port, &pagesize);

vm_statistics_data_t vm_stat;

if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS)
NSLog(@"Failed to fetch vm statistics");

/* Stats in bytes */
natural_t mem_used = (vm_stat.active_count +
vm_stat.inactive_count +
vm_stat.wire_count) * pagesize;
natural_t mem_free = vm_stat.free_count * pagesize;
natural_t mem_total = mem_used + mem_free;
NSLog(@"used: %u free: %u total: %u", mem_used, mem_free, mem_total);
}
--------------------------------------------------------------------------------
// We're just starting a game and a function for loading textures is called:
- (void) carregaMosques
{
[self print_free_memory];

texMoscaNormal[0][0] = [[Image alloc] initWithImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sangnormal01" ofType:@"png"]]];
texMoscaNormal[0][1] = [[Image alloc] initWithImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sangnormal02" ofType:@"png"]]];
texMoscaNormal[0][2] = [[Image alloc] initWithImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sangnormal03" ofType:@"png"]]];
texMoscaNormal[1][0] = [[Image alloc] initWithImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"gana" ofType:@"png"]]];
texMoscaNormal[1][1] = [[Image alloc] initWithImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"mnormalenrampa01" ofType:@"png"]]];
texMoscaNormal[1][2] = [[Image alloc] initWithImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"mnormalenrampa02" ofType:@"png"]]];
texMoscaNormal[2][0] = [[Image alloc] initWithImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"mnormal01" ofType:@"png"]]];
texMoscaNormal[2][1] = [[Image alloc] initWithImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"mnormal02" ofType:@"png"]]];
texMoscaNormal[2][2] = [[Image alloc] initWithImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"mnormal03" ofType:@"png"]]];

[self print_free_memory];
}
---------------------------------------------------------------------------
// Once the game is finished, a function for releasing loaded textures is called:
- (void) netejaMosques
{
[self print_free_memory];

[texMoscaNormal[0][0] release];
[texMoscaNormal[0][1] release];
[texMoscaNormal[0][2] release];
[texMoscaNormal[1][0] release];
[texMoscaNormal[1][1] release];
[texMoscaNormal[1][2] release];
[texMoscaNormal[2][0] release];
[texMoscaNormal[2][1] release];
[texMoscaNormal[2][2] release];

[self print_free_memory];
}
************************************************** *******

I've supposed that all the memory allocated in the first function is going to be released in the second function but, voilà! Memory increases when loading textures, but don't decreases when releasing textures! So, every time a game starts, same textures are loaded and it's memory space is NEVER freed (of course, there are much many functions that loads much many textures, but all of them are like this one, so it's the same case...).

What NSLog showed while tracing the game?

************************************************** *******
...[7868:207] Funcio CarregaMosques
...[7868:207] used: 2120642560 free: 2176602112 total: 2277376
...[7868:207] used: 2123165696 free: 2174124032 total: 2322432
(... some traces...)
...[7868:207] Funcio netejaMosques
...[7868:207] used: 2127245312 free: 2169683968 total: 1961984
...[7868:207] used: 2127245312 free: 2169704448 total: 1982464
************************************************** *******

So, as you can see, used memory increases when textures are loaded (of course), but used memory don't decreases when textures are released (eing?)!
I've also traced the textures retainCount and, as I've expected, retainCount just after calling release function is 1, so everything's OK...

What can be happening here? It have no sense! Is the end of the world here?

Any help you be madly appreciated! Thanks in advance!

Last edited by Johanovski; 12-23-2009 at 12:19 PM.
Johanovski is offline   Reply With Quote
Old 12-23-2009, 12:37 PM   #2 (permalink)
Registered Member
 
Join Date: Jun 2009
Posts: 825
Default

It's possible the Image class is doing some caching. I had a problem with images never being released in earlier versions of the OS, but that was with the ImageNamed method.
TunaNugget is offline   Reply With Quote
Old 12-23-2009, 12:42 PM   #3 (permalink)
Registered Member
 
scotopia's Avatar
 
Join Date: Oct 2008
Posts: 2,028
Default

Try tracing the retaincount of an object you are trying to release; its possible you are somehow retaining it one more time than you think you are and thus the release call won't actually free the object in memory.
scotopia is offline   Reply With Quote
Old 12-23-2009, 12:45 PM   #4 (permalink)
Dr. Touch Cocoa Helpdesk
iPhone Dev SDK Supporter
 
Join Date: Sep 2008
Location: Vienna, Austria
Posts: 537
Send a message via AIM to Oliver Drobnik Send a message via MSN to Oliver Drobnik Send a message via Skype™ to Oliver Drobnik
Default

Quote:
Originally Posted by TunaNugget View Post
It's possible the Image class is doing some caching. I had a problem with images never being released in earlier versions of the OS, but that was with the ImageNamed method.
output the retain count of the Image instances you are releasing. I bet that it's not 1 and thus the release does not put it to zero.
__________________
regards

Oliver Drobnik
Cocoanetics - Our DNA is programmed in Objective-C.

Linguan – makes localizing strings file fun!

Cocoanetics Parts Store – easy to use yet professionally looking components that you can use to spruce up your own apps. Augmented Reality, Calendar Control, Pin Lock or Purchase Button are only some examples. You get full source code, no static library crap, and lifetime support. Check it out today!
Oliver Drobnik is offline   Reply With Quote
Old 12-23-2009, 12:52 PM   #5 (permalink)
Maker of Games
 
Mr Jack's Avatar
 
Join Date: Nov 2009
Location: Coventry, UK
Posts: 395
Default

Looks to me like the UIImage's you're creating and initialising the Image's which you are releasing with might not be being released.
__________________


Visit Mr Jack Games for my blog and more about my games
Mr Jack is offline   Reply With Quote
Old 12-23-2009, 01:02 PM   #6 (permalink)
Registered Member
 
Join Date: Nov 2008
Posts: 791
Default

The retainCount after release is 1 ? It will only be dealloc'ed if it reaches 0.
What is the retainCount just after you place it in your array ?

Also, do you have a proper NSAutoreleasePool in place ? The [UIImage imageWith...] is autoreleased thus need one to release stuff.
nobre84 is offline   Reply With Quote
Old 12-23-2009, 01:07 PM   #7 (permalink)
Registered Member
 
scotopia's Avatar
 
Join Date: Oct 2008
Posts: 2,028
Default

Quote:
Originally Posted by Oliver Drobnik View Post
output the retain count of the Image instances you are releasing. I bet that it's not 1 and thus the release does not put it to zero.
Lol; beat you to it
scotopia is offline   Reply With Quote
Old 12-23-2009, 01:08 PM   #8 (permalink)
Registered Member
 
scotopia's Avatar
 
Join Date: Oct 2008
Posts: 2,028
Default

Yeah; this is a common thing that is forgotten when you add an object to an array, for instance; the object is going to get retained again (above and beyond its original allocation).
scotopia is offline   Reply With Quote
Old 12-24-2009, 03:40 AM   #9 (permalink)
Divine avenger
 
Johanovski's Avatar
 
Join Date: Nov 2009
Location: Vic, Catalunya (Spain)
Posts: 320
Default

Hi there!

I've checked array's (0,0) retainCount (which is an image) and it's 1 just before calling release. When trying to check after release an Exc bad acces is thrown (message sent to deallocated instance), so I've supposed release is correctly releasing the object (or maybe it just releases the array position? No idea of what is really doing, so it's not what I've thought since the beginning of the world...).
Something related to the array, you've said? Don't know why and what could be doing (or not doing)...
Any idea about this? I'm really at the edge of madness...

Thanks!
Johanovski is offline   Reply With Quote
Old 12-24-2009, 04:21 AM   #10 (permalink)
Maker of Games
 
Mr Jack's Avatar
 
Join Date: Nov 2009
Location: Coventry, UK
Posts: 395
Default

Did you look at whether it's the UIImage hanging around as I suggested?

Try storing the UIImage's your using to initialise your Image's with in a different array and explicitly freeing them.
__________________


Visit Mr Jack Games for my blog and more about my games
Mr Jack is offline   Reply With Quote
Old 12-24-2009, 05:12 AM   #11 (permalink)
Divine avenger
 
Johanovski's Avatar
 
Join Date: Nov 2009
Location: Vic, Catalunya (Spain)
Posts: 320
Default

Hi Mr Jack!

I'm trying to do what you've said (or what I think you've said) but I'm not able to... If I'm not wrong (and I think I'm ^_^) what I have to do is to allocate each UIImage before initializing the Image class and then releasing the UIImage, right? So, it should be something like this:

************************************************** **************
UIImage* img = [[UIImage alloc] initWithContentsOfFile:[...]];

texMoscaNormal[0][0] = [[Image alloc] initWithImage:img];

[img release];
************************************************** **************

But it's not possible to allocate a UIImage (don't know why, but it's not possible), so I have no idea of what you're meaning... Sorry, I'm quite new to iPhone development and OpenGL...

Thanks!
Johanovski is offline   Reply With Quote
Old 12-24-2009, 05:33 AM   #12 (permalink)
Maker of Games
 
Mr Jack's Avatar
 
Join Date: Nov 2009
Location: Coventry, UK
Posts: 395
Default

[UIImage initWithContentsOfFile:] creates and returns a UIImage. It is your responsiblity to clean up this returned UIImage.

The [UIImage alloc] is happening inside the initWithContentsOfFile: call which is a static member of UIImage so needs no object to be called on.
__________________


Visit Mr Jack Games for my blog and more about my games
Mr Jack is offline   Reply With Quote
Old 12-24-2009, 06:29 AM   #13 (permalink)
Divine avenger
 
Johanovski's Avatar
 
Join Date: Nov 2009
Location: Vic, Catalunya (Spain)
Posts: 320
Default

Hi Jack!

I thought method "imageWithContentsOfFile" didn't cache the image, so there's no need to release it... The returned image is needed to be allocated because it's being used every game's frame, so I can't release the Image class (the one is stored in the array) but, as I've explained, I thought the UIImage is never allocated, just created, returned, stored in the Image class as I've expected, and then destroyed (so a UIImage object is created, a Image object is then allocated and created from the UIImage returned object, and then no UIImage is stored)...
Does it works as I expect? If not (what I suppose), what I have to do to release the UIImage, if I have no object to call release (and no idea of how to autorelease an object, and even if it's possible)?

Thanks, and sorry for my newbie questions...
Johanovski is offline   Reply With Quote
Old 12-24-2009, 07:14 AM   #14 (permalink)
Maker of Games
 
Mr Jack's Avatar
 
Join Date: Nov 2009
Location: Coventry, UK
Posts: 395
Default

Quote:
Originally Posted by Johanovski View Post
I thought method "imageWithContentsOfFile" didn't cache the image, so there's no need to release it...
Caching and needing to release are not the same thing.

[UIImage imageWithContentsOfFile] returns a UIImage*, this points to a UIImage object containing the image you requested. You need to release this yourself, to do this you just need to store the returned UIImage* and then call release on it when you are done with it. You do not need to call alloc because initWithContentsOfFile has already allocated the object.

Now, had you used imageNamed instead it would return a pointer to a UIImage object you would need to release and it would internally cache a copy of the image so that the next time you call ImageNamed it will load near instantly. That's what caching is.

Quote:
...I thought the UIImage is never allocated, just created, returned, stored...
How did you expect it to be created without being allocated?
__________________


Visit Mr Jack Games for my blog and more about my games
Mr Jack is offline   Reply With Quote
Old 12-24-2009, 07:36 AM   #15 (permalink)
Divine avenger
 
Johanovski's Avatar
 
Join Date: Nov 2009
Location: Vic, Catalunya (Spain)
Posts: 320
Default

Hi again!

I think I understand what you mean, but still not knowing how to make it works... I've tried with the following code:

************************************************** ***
UIImage* img = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sangnormal01" ofType:@"png"]];
texMoscaNormal[0][0] = [[Image alloc] initWithImage:img];
[img release];
************************************************** ***

So a UIImage* is created, the UIImage is allocated inside it's own method (so no additional alloc is called), then the Image class is initialized with a UIImage, and after this the UIImage* is released... I think this is the theory, more or less, but when I try to run the app...

----------------------------------------------------------------------
[1541:207] *** -[UIImage release]: message sent to deallocated instance 0x3b37a20
----------------------------------------------------------------------

Seems that log says UIImage is never allocated, so releasing is not possible... it's losing sense as time passes!

Thanks Jack!
Johanovski is offline   Reply With Quote
Old 12-24-2009, 11:26 AM   #16 (permalink)
Maker of Games
 
Mr Jack's Avatar
 
Join Date: Nov 2009
Location: Coventry, UK
Posts: 395
Default

Hmm... I'm afraid I don't really know what else to suggest. I don't use initWithContentsOfFile.
__________________


Visit Mr Jack Games for my blog and more about my games
Mr Jack is offline   Reply With Quote
Old 12-24-2009, 11:37 AM   #17 (permalink)
Registered Member
 
Join Date: Apr 2009
Posts: 536
Default

Quote:
Originally Posted by Johanovski View Post
Code:
UIImage* img = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sangnormal01" ofType:@"png"]];
texMoscaNormal[0][0] = [[Image alloc] initWithImage:img];
[img release];  // <-- You don't want this
I haven't read the whole thread, but just commenting on this last post...

+[UIImage imageWithContentsOfFile] will return a UIImage that has been autoreleased.

So you don't want to release it again.

And then of course you want to make sure that -[Image initWithImage:] is retaining the UIImage and releasing it in -[Image dealloc].

Hope that helps.
eddietr is offline   Reply With Quote
Old 01-04-2010, 02:48 AM   #18 (permalink)
Divine avenger
 
Johanovski's Avatar
 
Join Date: Nov 2009
Location: Vic, Catalunya (Spain)
Posts: 320
Default

Hi there!

Back from Christmas, and having to face the same (still unsolved) problem again... As it seems it have no sense that releasing images don't free memory at all, I've tried doing a test function to ensure that allocating and releasing variables is really affecting memory as it should do, so I've done the following:

************************************************** ***********
NSLog(@"Strings!");
[self print_free_memory];

NSString* things[400];

for (int i=0; i<400; i++) {
things[i] = [[NSString alloc] initWithString:@"Yabadabadoo!"];
}

[self print_free_memory];

for (int i=0; i<400; i++) {
[things[i] release];
}

[self print_free_memory];
************************************************** ***********

And what I get in the console, running in the 3.1.2 OS simulator in debug mode is:

************************************************** ***********
...[710:207] Strings!
...[710:207] used: 1547698176 free: 2749194240 total: 1925120
...[710:207] used: 1547710464 free: 2749214720 total: 1957888
...[710:207] used: 1547722752 free: 2749235200 total: 1990656
************************************************** ***********

What the #%&"?? Seems that used memory don't decrease even when I release 400 allocated NSStrings? Does it really have sense...?

Thanks, any help will be really appreciated!
Johanovski is offline   Reply With Quote
Old 01-04-2010, 02:50 AM   #19 (permalink)
Divine avenger
 
Johanovski's Avatar
 
Join Date: Nov 2009
Location: Vic, Catalunya (Spain)
Posts: 320
Default

Sorry, I've forget copying the print_free_memory function too:

************************************************** ************
- (void) print_free_memory {
mach_port_t host_port;
mach_msg_type_number_t host_size;
vm_size_t pagesize;

host_port = mach_host_self();
host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
host_page_size(host_port, &pagesize);

vm_statistics_data_t vm_stat;

if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS)
NSLog(@"Failed to fetch vm statistics");

/* Stats in bytes */
natural_t mem_used = (vm_stat.active_count +
vm_stat.inactive_count +
vm_stat.wire_count) * pagesize;
natural_t mem_free = vm_stat.free_count * pagesize;
natural_t mem_total = mem_used + mem_free;
NSLog(@"used: %u free: %u total: %u", mem_used, mem_free, mem_total);
}
************************************************** ************

Thanks!
Johanovski is offline   Reply With Quote
Old 01-04-2010, 12:12 PM   #20 (permalink)
Senior Member
iPhone Dev SDK Supporter
 
smasher's Avatar
 
Join Date: Jul 2008
Location: San Mateo, CA (San Fran)
Posts: 3,858
Default

Quote:
Originally Posted by Johanovski View Post
What the #%&"?? Seems that used memory don't decrease even when I release 400 allocated NSStrings? Does it really have sense...?

Thanks, any help will be really appreciated!
Change that to mutableStrings and you'll probably get the results you're expecting. [[NSString alloc] initWithString:@"Yabadabadoo!"] will have the same result as just writing @"Yabadabadoo!" , which is a static string that doesn't get deallocated at all during the life of your program.

RE: your images releasing, I think someone pointed out in another thread that your Texture2D dealloc call was not deleting the openGL texture.
__________________

Free Games!
smasher is offline   Reply With Quote
Reply

Bookmarks

Tags
alloc, memory, release, retaincount

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: 271
17 members and 254 guests
ADY, Alsahir, Dani77, Desert Diva, Duncan C, F_Bryant, Grinarn, HemiMG, Herbie, jansan, linkmx, M@realobjects, macquitzon216, prchn4christ, smethorst, spiderguy84
Most users ever online was 1,187, 10-11-2011 at 08:09 AM.
» Stats
Members: 158,882
Threads: 89,228
Posts: 380,761
Top Poster: BrianSlick (7,129)
Welcome to our newest member, jansan
Powered by vBadvanced CMPS v3.1.0

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