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 Game Development

Reply
 
LinkBack Thread Tools Display Modes
Old 06-06-2010, 04:19 PM   #1 (permalink)
Registered Member
 
Join Date: Apr 2010
Posts: 18
ImpGuard is on a distinguished road
Default EXC_BAD_ACCESS help?

I read up on this error and it's supposedly thrown when I access a variable or object that has been released. But I'm not sure how to fix this error! I'm using Cocos2D to program a basic SpriteController that keeps track of all my Sprites and sends them a touchBegan: to keep track of touches.

I made a Basic HelloWorldScene.m that initializes like this:

Quote:
-(id) init
{
if( (self=[super init] )) {

[SpriteController addSprite:[TouchBox touchBoxWithFile: @"red1.gif"]];
[[[SpriteController allMySprites] lastObject] setPosition: ccp(360, 180)];
[self addChild:[[SpriteController allMySprites] lastObject]];


[SpriteController addSprite:[TouchBox touchBoxWithFile: @"red1.gif"]];
[[[SpriteController allMySprites] lastObject] setPosition: ccp(120, 180)];
[self addChild:[[SpriteController allMySprites] lastObject]];


[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self
priority:0
swallowsTouches:YES];
}
return self;
}
And then, when the Scene is touched, I pass it on to the SpriteController

Quote:
- (BOOL) ccTouchBegan: (UITouch *)touch withEvent: (UIEvent *)event
{
CGPoint location = [[CCDirector sharedDirector] convertToGL: [touch locationInView: [touch view]]];

BOOL anyoneTouched = [SpriteController sendTouchBegan:location];

return anyoneTouched;
}
Finally, the SpriteController loops through all its Sprites, checks if they respond to touchBegan: and sends them the command.

Quote:
+(BOOL) sendTouchBegan: (CGPoint) cgp
{
BOOL touched = FALSE;

if (allMySprites == nil) {
//touched = false;
} else {
for (CCSprite *sprite in allMySprites) {
if([sprite respondsToSelector:@selector(touchBegan: )]) {
touched = [sprite touchBegan: cgp];
}
}
}

return touched;
}
The program displays the 2 red1.gif boxes on the screen during initialization fine. And after debugging around, I figured that the flow of the program does enter the TouchBegan and is passed to the SpriteController. However, as soon as I begin looping through allMySprites, I get the EXC_BAD_ACCESS error. After playing around with it, I determined that I simply can't access any of the objects in allMySprites beyond initialization. So even if I added a [allMySprites lastObject] directly in the scene, it'd throw the error. Why can't I access the objects in allMySprites? They don't seem to be released by the time I want to use them, but it just doesn't let me touch them.

EDIT: Removed all the smiley's in my code
ImpGuard is offline   Reply With Quote
Old 06-06-2010, 05:45 PM   #2 (permalink)
Registered Member
iPhone Dev SDK Supporter
 
smasher's Avatar
 
Join Date: Jul 2008
Location: San Mateo, CA (San Fran)
Posts: 3,858
smasher will become famous soon enough
Default

You might get this error if the array that "allMySprites" points to is autoreleased and not retained. How do you create that array?

Any time someone says "my object works when I create it, but not later" it's usually an autorelease problem.
__________________

Free Games!
smasher is offline   Reply With Quote
Old 06-06-2010, 08:26 PM   #3 (permalink)
Registered Member
 
Join Date: Apr 2010
Posts: 18
ImpGuard is on a distinguished road
Default

Quote:
Originally Posted by smasher View Post
You might get this error if the array that "allMySprites" points to is autoreleased and not retained. How do you create that array?

Any time someone says "my object works when I create it, but not later" it's usually an autorelease problem.
Sorry, forgot to point that out. When I add a sprite to the allMySprites array, it automatically checks to see if allMySprites has been created, and if not, calls:

allMySprites = [NSMutableArray array];

to actually create the array. Though I'm new at this kind of programming, I recall that any object not created by me (not using alloc, new, copy) is automatically handled by the system. By creating allMySprites using Apple's API for NSMutableArray, shouldn't it automatically be handled, autoreleased/retained for me?
ImpGuard is offline   Reply With Quote
Old 06-06-2010, 11:22 PM   #4 (permalink)
Registered Member
iPhone Dev SDK Supporter
 
smasher's Avatar
 
Join Date: Jul 2008
Location: San Mateo, CA (San Fran)
Posts: 3,858
smasher will become famous soon enough
Default

Quote:
Originally Posted by ImpGuard View Post
Though I'm new at this kind of programming, I recall that any object not created by me (not using alloc, new, copy) is automatically handled by the system. By creating allMySprites using Apple's API for NSMutableArray, shouldn't it automatically be handled, autoreleased/retained for me?
No, "autoreleased" doesn't mean that the memory is managed for you; it means that the object will be released at the end of the current event, and possibly destroyed unless you retain it in some way. You will have to learn the retain/release rules to make a working program.

Objective-C Beginner's Guide

In your case, this should do the trick:
Code:
allMySprites = [[NSMutableArray alloc] init];
Now allMySprites will stick around until you release it.
__________________

Free Games!
smasher is offline   Reply With Quote
Old 06-07-2010, 03:27 AM   #5 (permalink)
Registered Member
 
Join Date: Apr 2010
Posts: 18
ImpGuard is on a distinguished road
Default

Quote:
Originally Posted by smasher View Post
No, "autoreleased" doesn't mean that the memory is managed for you; it means that the object will be released at the end of the current event, and possibly destroyed unless you retain it in some way. You will have to learn the retain/release rules to make a working program.

Objective-C Beginner's Guide

In your case, this should do the trick:
Code:
allMySprites = [[NSMutableArray alloc] init];
Now allMySprites will stick around until you release it.
Wait, doesn't autorelease add the object into the pool to be drained? If what you're saying is true, then it makes sense. Do you know how often or when Cocos2D drains the AutoReleasePool? In my knowledge, I know that the array returned with [NSMutableArray array] is autoreleased by Apple, but I would think that the pool is drained at the end of the program (when the scene switches or the program is turned off). Am I wrong to assume this?
ImpGuard is offline   Reply With Quote
Old 06-07-2010, 03:31 AM   #6 (permalink)
A Single-Serving Friend
 
Join Date: Mar 2010
Location: Groningen, NL
Posts: 491
Robert Paulson is on a distinguished road
Default

As smasher said, the pool is drained after each event. Or at least, that is what you should assume. If you create an autoreleased object within a method, you can assume that it will be destroyed after the method is executed.

If the routine waited until the end of the programme/until you close the app, there would be no "release". At least not effectively as you'd hang on to all objects until the end of the app. That's what you want to avoid! Get rid of objects as soon as you can (read: as soon as you don't need them anymore) in order to free memory again so you can use it for something else.

Cheers,
Bob
__________________
We are God’s middle children, according to Tyler Durden, with no special place in history and no special attention.

Consider saying thanks by buying my app. :]
Robert Paulson is offline   Reply With Quote
Old 06-07-2010, 03:54 PM   #7 (permalink)
Registered Member
 
Join Date: Apr 2010
Posts: 18
ImpGuard is on a distinguished road
Default

Quote:
Originally Posted by Robert Paulson View Post
As smasher said, the pool is drained after each event. Or at least, that is what you should assume. If you create an autoreleased object within a method, you can assume that it will be destroyed after the method is executed.

If the routine waited until the end of the programme/until you close the app, there would be no "release". At least not effectively as you'd hang on to all objects until the end of the app. That's what you want to avoid! Get rid of objects as soon as you can (read: as soon as you don't need them anymore) in order to free memory again so you can use it for something else.

Cheers,
Bob
Alright, that makes sense. That's knowledge I didn't know. So the pool is drained after every event? That clarifies things. I'll fix it up and see if it works now!
ImpGuard 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: 407
10 members and 397 guests
7twenty7, ChrisYates, djohnson, Duncan C, gmarro, Kirkout, Retouchable, SLIC, walex, xzoonxoom
Most users ever online was 1,387, 04-10-2012 at 04:21 AM.
» Stats
Members: 175,679
Threads: 94,128
Posts: 402,921
Top Poster: BrianSlick (7,990)
Welcome to our newest member, xzoonxoom
Powered by vBadvanced CMPS v3.1.0

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