Constant, random and inexplicable (to me, anyway) EXC BAD ACCESS in Objective C app
-
09-03-2021 - |
Question
I have Automatic Reference Counting and Zombies enabled...
I keep getting EXC BAD ACCESS to different points in the code, most of the time with no further information coming from zombies.
The objective is to draw a rectangle to the screen with a texture on it that is loaded from an image. It does actually work! But often it is corrupted (the image and the vectors) and then often I just get the exc bad access warning.
I have this sort of structure...
App Delegate Class Declaration:
GWBackgroundScene* background;
EAGLContext *context;
GLKView *view;
GLKViewController *controller;
UIWindow *window;
and then window is made into a property and synthesized.
The did Finish Launching With Options:
context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
[EAGLContext setCurrentContext:context];
view = [[GLKView alloc] initWithFrame:[[UIScreen mainScreen] bounds] context:context];
view.delegate = self;
controller = [[GLKViewController alloc] init];
[controller shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationPortrait];
controller.delegate = self;
controller.view = view;
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = controller;
[self.window makeKeyAndVisible];
background = [[GWBackgroundScene alloc] initWithImage:[UIImage imageNamed:@"DSC_0059.jpg"]];
The AppDelegate acts as an OpenGL delegate and OpenGL calls a function called 'render' in the class which then calls [background render];
My GWBackgroundScene class:
@interface GWBackgroundScene : NSObject
{
GLKTextureInfo *texture;
NSMutableData* vertexData;
NSMutableData* textureCoordinateData;
}
@property(readonly) GLKVector2 *vertices;
@property(readonly) GLKVector2 *textureCoordinates;
-(void) render;
-(id) initWithImage: (UIImage*)image;
Initialises with:
self = [super init];
if(self != nil)
{
texture = [GLKTextureLoader textureWithCGImage:image.CGImage options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:GLKTextureLoaderOriginBottomLeft] error:&error];
vertexData = [NSMutableData dataWithLength:4];
textureCoordinateData = [NSMutableData dataWithLength:4];
self.vertices[0] = GLKVector2Make(-2.0,3.0);
...
self.textureCoordinates[0] = GLKVector2Make(0,0);
...
}
return self;
and has these two functions for dealing with the vector and texture information
- (GLKVector2 *)vertices {
return [vertexData mutableBytes];
}
- (GLKVector2 *)textureCoordinates {
return [textureCoordinateData mutableBytes];
}
and then the render function (which is called by OpenGL via its delegate (the App delegate) uses:
texture:
GLKBaseEffect *effect = [[GLKBaseEffect alloc] init]; effect.texture2d0.envMode = GLKTextureEnvModeReplace; effect.texture2d0.target = GLKTextureTarget2D; effect.texture2d0.name = texture.name;
self.vertices:
glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, 0, self.vertices);
self.textureCordinates
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 0, self.textureCoordinates);
What are the obvious memory issues with what im doing?
Thanks very much
Solution
You create an NSMutableData object with size 4 bytes, but the data type GLKVector2 is larger than 1 byte. If you're expecting to store a few objects in there you should do
vertexData = [NSMutableData dataWithLength:4 * sizeof(GLKVector2)];
And similarly for textureCoordinateData.