App Crashing When Calling Release on Autorelease Pool - Timing Issue ? iPhone - iphone

I have the following method in my app :
- (void) loadModel {
// Runs in a seperate thread so we need to create an additional NSAutoreleasePool
pool = [[NSAutoreleasePool alloc] init];
NSData *getData = [activeModelInfo getFileData];
if (getData) {
if ([activeModel loadFromFileData:daeData]) {
[activeModel reset];
[mainViewController performSelectorOnMainThread:#selector(showModelView) withObject:nil waitUntilDone:NO];
}
else {
}
}
else {
}
[pool release];
}
The loadFromFileData method calls the following code which loads data. :
- (void) loadVerticesFromSource:(NSString*)verticesSourceId meshNode:(TBXMLElement*)meshNode intoMesh: (Mesh3D*) mesh {
NSLog(#"Getting Vertices for Source %#",verticesSourceId);
FloatArray *floatArray = [self getFloatArrayFromSource: verticesSourceId meshNode: meshNode];
if (floatArray) {
[daeFloatArray addObject:floatArray];
}
if (floatArray) {
if ([floatArray.array count] % 3 != 0) {
NSLog(#"Float array length not divisible by 3!");
}
else {
mesh->verticesCount = [floatArray.array count] / 3;
mesh->vertices = malloc(sizeof(Vector3D) * mesh->verticesCount);
for (int i=0; i<mesh->verticesCount; i++) {
mesh->vertices[i].x = [[floatArray.array objectAtIndex:(i*3)] floatValue];
mesh->vertices[i].y = [[floatArray.array objectAtIndex:(i*3)+1] floatValue];
mesh->vertices[i].z = [[floatArray.array objectAtIndex:(i*3)+2] floatValue];
// update extents information
if (!extents.pointDefined || mesh->vertices[i].x < extents.minX) extents.minX = mesh->vertices[i].x;
else if (!extents.pointDefined || mesh->vertices[i].x > extents.maxX) extents.maxX = mesh->vertices[i].x;
if (!extents.pointDefined || mesh->vertices[i].y < extents.minY) extents.minY = mesh->vertices[i].y;
else if (!extents.pointDefined || mesh->vertices[i].y > extents.maxY) extents.maxY = mesh->vertices[i].y;
if (!extents.pointDefined || mesh->vertices[i].z < extents.minZ) extents.minZ = mesh->vertices[i].z;
else if (!extents.pointDefined || mesh->vertices[i].z > extents.maxZ) extents.maxZ = mesh->vertices[i].z;
if (!extents.pointDefined) extents.pointDefined = YES;
[pointerStorageArray addObject:[NSValue valueWithPointer:mesh->vertices]];
}
}
}
}
Since this method is called several times while the data loads, each time mallocing memory for the mesh->vertices struct, I have created a pointerStorage array where I store the pointer to the malloced memory.
The app then displays a 3D object using OpenGL ES. When the user presses a Main Menu button, I then free up the pointerStorageArray as follows :
- (void) freeUpMallocedMemory
for (NSValue * value in pointerStorageArray) {
free(value);
}
The problem is that the app then crashes during this process. All I get is the EXC_BAD_ACCESSS error message and a pointer to the following line of code in the loadModel method above :
[pool release];
Nothing in the stack trace. I have also tried turning on NSZombie, NSAutoreleaseTrackFreedObjectCheck and NSDebugEnabled, but I still don't get any additional information.
The odd thing is that if I put a delay on the button of 2 seconds (i.e only trigger the freeUpMallocedMemory method after 2 seconds), the app no longer crashes and works fine.
Can anyone suggest what might be causing this - really confused and have already spent a few days troubleshooting.
Thank you !

You are over-releasing... the values in pointerStorageArray are created via a convenience method and as such don't need releasing, simply removing them from the array will dispose of them.

Related

"pointer being freed was not allocated" error with core plot array

I'm drawing a waveform of the incoming audio in the microphone by using core plot.
It works great but i sometime get this error :
malloc: * error for object 0x175a1550: pointer being freed was not allocated
* set a breakpoint in malloc_error_break to debug.
It happens occasionally (after 1 minute, 10 minutes, 1 hour...it depends!) when the core plot array is being cleared.
-(void)refreshScope: (NSTimer*)theTimer;
{
if ([[audio dataForScope] count] == 500)
{
[self performSelectorOnMainThread:#selector(reloadDataOnMainThread) withObject:nil waitUntilDone:YES];
[[audio dataForScope] removeAllObjects]; // HERE !!!!
}
}
-(void) reloadDataOnMainThread
{
[audioScope reloadData];
}
The dataForScope array (mutable) is alloc/init in the audio class of my code. It is filled with integer of the audio buffer.
I have tried a lot of different things but nothing seems to work. I always get the same error
Any ideas ?
Thank you.
EDIT :
-(void)processAudio:(AudioBufferList *)bufferList{
AudioBuffer sourceBuffer = bufferList->mBuffers[0];
memcpy(tempBuffer.mData, bufferList->mBuffers[0].mData, bufferList->mBuffers[0].mDataByteSize);
int16_t* samples = (int16_t*)(tempBuffer.mData);
#autoreleasepool
{
for ( int i = 0; i < tempBuffer.mDataByteSize / 2; ++i )
{
if(i % 5 == 0)
{
if ([dataForScope count] == 500)
{
scopeIndex = 0;
}
else
{
float scopeTime = scopeIndex * 1000.0 / SampleRate;
id xScope = [NSNumber numberWithFloat: scopeTime];
id yScope = [NSNumber numberWithInt: samples[i]/100];
[dataForScope addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:xScope, #"xScope", yScope, #"yScope", nil]];
}
scopeIndex = scopeIndex + 1;
}
}
}
Make sure [[audio dataForScope] removeAllObjects]; executes before you call -reloadData on the plot. This ensures the dataForScope array is ready whenever the plot requests its new data.
The plot datasource methods are called on the main thread. If they read the dataForScope array directly, you need to make sure all accesses to that array (reads and writes) occurs on the main thread so there are no conflicts.

Why am I getting exc_bad_access errors for objectAtIndex in my floodfill algorithm

I have a flood fill function:
-(void) fillArea :(int) fillNum x:(int) xSpot y:(int) ySpot
{
int gridValue = 1;
int gridCount = [theGrid count];
[[theGrid objectAtIndex:(xSpot+ySpot*120)] getValue:&gridValue];
if (gridValue != 0) {
return;
}
[theGrid replaceObjectAtIndex:(xSpot + ySpot*120) withObject:[NSNumber numberWithInt:fillNum]];
[self fillArea:fillNum x:(xSpot+1) y:(ySpot)];
[self fillArea:fillNum x:(xSpot+1) y:(ySpot-1)];
[self fillArea:fillNum x:(xSpot) y:(ySpot-1)];
[self fillArea:fillNum x:(xSpot-1) y:(ySpot-1)];
[self fillArea:fillNum x:(xSpot-1) y:(ySpot)];
[self fillArea:fillNum x:(xSpot-1) y:(ySpot+1)];
[self fillArea:fillNum x:(xSpot) y:(ySpot+1)];
[self fillArea:fillNum x:(xSpot+1) y:(ySpot+1)];
return;
}
theGrid is an NSMutableArray of ints (either a 0 or a 1). It is just a 1D array that simulates a 2D array by multiplying the ySpot by 120 (the width of my grid). I checked the gridCount and it is equal to 9600.
However, I get an exc_bad_access at [[theGrid objectAtIndex:(xSpot+ySpot*120)] getValue:&gridValue]. I check my xSpot and ySpot when this happens and I know that (xSpot+ySpot*120) < 9600 every time. So I know it's not that I'm trying to access an object who's index is outside my array.
Futhermore, in my tick function I ran the code:
int gVal = 1;
int gIndex = 0;
while (gIndex < [theGrid count]) {
[[theGrid objectAtIndex:gIndex] getValue:&gVal];
gIndex += 1;
}
I did not get an exc_bad_access error. Please help me figure out why I'm getting an exc_bad_access error.
EDIT:
I split [[theGrid objectAtIndex:(xSpot+ySpot*120)] getValue:&gridValue]; into:
id object = [theGrid objectAtIndex:(xSpot+ySpot*widthInGridSize)];
gridValue = [object intValue];
I still get exc_bad_access and it says it is on the line:
gridValue = [object intValue];
So I assume this means object has already been released? I don't understand how that's possible. I thought ints didn't need to be retained in any way since they're just ints. Also I thought adding an object to an array automatically retained it so why would my int get released.
In the debug section the value of object is said equal: (_NSCFNumber *) 0x005aec80 (int) 0
As per comments - this isn't actually an out of bounds issue, but rather the object you're pulling out of 'theGrid' is bogus (already released). Break that into multiple lines to confirm; and turn on "zombies" in your debug settings. Cheers!

Crash due to removal of Elements like CCSprite from NSMutableArray

So, here's how it goes.
I am currently working on Cocos2d game, which consists of many Obstacles. One obstacle gets added on the screen at an interval of 10 seconds like this.
ObstacleSprite* newObstacle = [ObstacleSprite spriteWithFile:#"Obstacle.png" rect:CGRectMake(0, 0, 20, 20)];
newObstacle.position = ccp(mainPlayer1.position.x,10);
[self addChild:newObstacle];
[self.arrayForObstacles addObject:newObstacle];
Now, I insert these obstacles into the arrayForObstacles because I also want to keep checking whether the Obstacles and MainPlayer don't collide.
I check it with the help of this function.
- (void) checkCollisionWithObstacle
{
if(mainPlayer1.playerActive)
{
for(int i = 0; i < [self.arrayForObstacles count]; i++)
{
ObstacleSprite* newObstacle = [self.arrayForObstacles objectAtIndex:i];
if(newObstacle != nil)
{
if(CGRectIntersectsRect([mainPlayer1 boundingBox], [newObstacle boundingBox]))
{
mainPlayer1.livesLeft--;
}
}
}
}
}
THE ISSUE
Problem is when I get to certain score, one of the Obstacles gets deleted. Removal of Obstacles works as in First In-First Out (FIFO) mode. So, to delete obstacles, I write the following method :
- (void) keepUpdatingScore
{
//update new score
mainPlayer1.score+=10;
//remove obstacle when score increases by 5k
if(mainPlayer1.score > 5000 && mainPlayer1.score > 0)
{
mainPlayer1.playerActive = NO;
if([self.arrayForObstacles count] > 0)
{
CCLOG(#"count is %d",[self.arrayForObstacles count]);
ObstacleSprite* newObstacle = [self.arrayForObstacles objectAtIndex:0];
[self.arrayForObstacles removeObjectAtIndex:0];
[self removeChild:newObstacle cleanup:YES];
CCLOG(#"count is %d",[self.arrayForObstacles count]);
}
mainPlayer1.playerActive = YES;
}
else
{
}
It crashes when score crosses 5000 mark!
UPDATE
Crash happens when it again goes to the method checkCollisionWithObstacle.
This is the THREAD Look.
THis is the line Which crashes.
you seem to be using mainPlayer1.playerActive as a semaphore to block checking the checkCollisionWithObstacle loop from a delete in the keepUpdatingScore method (are they asynchronous ?). Assuming they are, the way you are blocking the loop access wont work if the code enters keepUpdatingScore AFTER the loop started in checkCollisionWithObstacle ... your mileage will vary.

Memory Leak question

I am having a memory leak issue with the following code. As much as I can tell I don't see why the problem persists but it still does not release when called. I am detecting the problem in instruments and the following code is keeping its "cards" classes alive even when it should had released them.
Any help welcome.
...
...
-(id)initDeckWithCardsPicked: (NSMutableArray*)cardsPicked andColors:(NSMutableArray*)cardColors
{
self = [self init];
if (self != nil) {
int count = [cardsPicked count];
for (int i=0; i<count; i++) {
int cardNum = [[cardsPicked objectAtIndex:i] integerValue];
Card * card = [[MemoryCard alloc] initWithSerialNumber:cardNum position: CGPointZero color:[cardColors objectAtIndex:i]];
[_cards addObject: card];
[card release];
}
}
return self;
}
- (id) init
{
self = [super init];
if (self != nil) {
self.bounds = (CGRect){{0,0},[Card cardSize]};
self.cornerRadius = 8;
self.backgroundColor = kAlmostInvisibleWhiteColor;
self.borderColor = kHighlightColor;
self.cards = [NSMutableArray array];
}
return self;
}
...
...
Without looking at the rest of your code, its hard to know where the problem is, but have you tried using the static analyzer in xcode? Its can be invaluable for finding memory leaks.
To use it, select 'Build and Analyze' from the Build menu. Further details are on Apple's dev website.
When you add a Card to the _cards NSMutableArray using addObject, it is sent a retain message. Thus, as long as you keep _cards in memory, a pointer will also be kept for each of it's constituents. As long as your dealloc releases the array, or you do so elsewhere, you shoul dbe fine with what you have posted here (assuming your initWithSerialNumber method returns a retained object).

Need help with a memory management problem in my game model

I'm a beginner level programmer trying to make a game app for the iphone and I've encountered a possible issue with the memory management (exc_bad_access) of my program so far. I've searched and read dozens of articles regarding memory management (including apple's docs) but I still can't figure out what exactly is wrong with my codes. So I would really appreciate it if someone can help clear up the mess I made for myself.
//in the .h file
#property(nonatomic,retain) NSMutableArray *fencePoleArray;
#property(nonatomic,retain) NSMutableArray *fencePoleImageArray;
#property(nonatomic,retain) NSMutableArray *fenceImageArray;
//in the .m file
- (void)viewDidLoad {
[super viewDidLoad];
self.gameState = gameStatePaused;
fencePoleArray = [[NSMutableArray alloc] init];
fencePoleImageArray = [[NSMutableArray alloc] init];
fenceImageArray = [[NSMutableArray alloc] init];
mainField = CGRectMake(10, 35, 310, 340);
..........
[NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:#selector(gameLoop) userInfo:nil repeats:YES];
}
So basically, the player touches the screen to set up the fences/poles
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if(.......) {
.......
}
else {
UITouch *touch = [[event allTouches] anyObject];
currentTapLoc = [touch locationInView:touch.view];
NSLog(#"%i, %i", (int)currentTapLoc.x, (int)currentTapLoc.y);
if(CGRectContainsPoint(mainField, currentTapLoc)) {
if([self checkFence]) {
onFencePole++;
//this 3 set functions adds their respective objects into the 3 NSMutableArrays using addObject:
[self setFencePole];
[self setFenceImage];
[self setFencePoleImage];
.......
}
}
else {
.......
}
}
}
}
The setFence function (setFenceImage and setFencePoleImage is similar to this)
-(void)setFencePole {
Fence *fencePole;
if (!elecFence) {
fencePole = [[Fence alloc] initFence:onFencePole fenceType:1 fencePos:currentTapLoc];
}
else {
fencePole = [[Fence alloc] initFence:onFencePole fenceType:2 fencePos:currentTapLoc];
}
[fencePoleArray addObject:fencePole];
[fencePole release];
and whenever I press a button in the game, endOpenState is called to clear away all the extra images(fence/poles) on the screen and also to remove all existing objects in the 3 NSMutableArray. Point is to remove all the objects in the NSMutableArrays but keep the array itself so it can be reused later.
-(void)endOpenState {
........
int xMax = [fencePoleArray count];
int yMax = [fenceImageArray count];
for (int x = 0; x < xMax; x++) {
[[fencePoleImageArray objectAtIndex:x] removeFromSuperview];
}
for (int y = 0; y < yMax; y++) {
[[fenceImageArray objectAtIndex:y] removeFromSuperview];
}
[fencePoleArray removeAllObjects];
[fencePoleImageArray removeAllObjects];
[fenceImageArray removeAllObjects];
........
}
The crash happens here at the checkFence function.
-(BOOL)checkFence {
if (onFencePole == 0) {
return YES;
}
else if (onFencePole >= 1 && onFencePole < currentMaxFencePole - 1) {
CGPoint tempPoint1 = currentTapLoc;
CGPoint tempPoint2 = [[fencePoleArray objectAtIndex:onFencePole-1] returnPos]; // the crash happens at this line
if ([self checkDistance:tempPoint1 point2:tempPoint2]) {
return YES;
}
else {
return NO;
}
}
else if (onFencePole == currentMaxFencePole - 1) {
......
}
else {
return NO;
}
}
So the problem here is, everything works fine until checkFence is called the 2nd time after endOpenState is called. So its like tap_screen -> tap_screen -> press_button_to_call_endOpenState -> tap screen -> tap_screen -> crash
What I'm thinking of is that fencePoleArray got messed up when I used [fencePoleArray removeAllObjects] because it doesn't crash when I comment it out. It would really be great if someone can explain to me what went wrong. And thanks in advance.
First, a couple of suggestions:
if (!elecFence) {
fencePole = [[Fence alloc] initFence:onFencePole
fenceType:1 fencePos:currentTapLoc];
}
else {
fencePole = [[Fence alloc] initFence:onFencePole
fenceType:2 fencePos:currentTapLoc];
}
You’re making this too hard, how about this:
const int fenceType = elecFence ? 2 : 1;
Fence *fencePole = [[Fence alloc] initFence:onFencePole
fenceType:fenceType fencePos:currentTapLoc];
And this:
int xMax = [fencePoleArray count];
int yMax = [fenceImageArray count];
for (int x = 0; x < xMax; x++) {
[[fencePoleImageArray objectAtIndex:x] removeFromSuperview];
}
for (int y = 0; y < yMax; y++) {
[[fenceImageArray objectAtIndex:y] removeFromSuperview];
}
Could be shortened using makeObjectsPerformSelector:
const SEL remove = #selector(removeFromSuperview);
[fencePoleImageArray makeObjectsPerformSelector:remove];
[fenceImageArray makeObjectsPerformSelector:remove];
This is shorter and safer, as the xMax bound in your code is computed from fencePoleArray and used to iterate over fencePoleImageArray. (Could be right, could be wrong.)
Now to the objectAtIndex: call. If the array is still in memory and you tried to access an object beyond the array bounds, you would get an exception. So that I guess that either the array or some of the objects in it got released without you knowing it. You could try to NSLog the array and the object on given index and try to log their retainCount. If the logging line crashes, you have found the object that’s been released and can start looking for the cause.
(And one more thing: You should split the game logic into a separate model class. This simplifies the code and makes it easier to reason about.)
If you want to use properties, you should use self.propertyName = ... instead of propertyName = ....
Hope this will help.