简体   繁体   English

Objective-c Opengl内存泄漏

[英]Objective-c Opengl memory leak

I'm having a memory leak in my iOS app when allocating many images to a single variable. 将多个图像分配给单个变量时,我的iOS应用程序出现内存泄漏。

A simplified version of my update function, but still demonstrates the point. 我的更新功能的简化版本,但仍然说明了这一点。

This is being called 10 times a second. 每秒被称为10次。 I need the Allocation to free after it renders but I'm not sure how to do it. 渲染后,我需要释放分配,但是我不确定该怎么做。

- (void) update
{
PSSprite * score1sDigit = [[PSSprite alloc] initWithFile:[NSString stringWithFormat:@"#%i.png", score%10] effect:self.effect];
}

I'm using this class to allocate memory for the for the texture and to render it 我正在使用此类为纹理分配内存并渲染它

#import <Foundation/Foundation.h>
#import <GLKit/GLKit.h>

@interface PSSprite : NSObject

@property (assign) GLKVector2 position;
@property (assign) CGSize contentSize;
@property (assign) GLKVector2 moveVelocity;

- (id)initWithFile:(NSString *)fileName effect:(GLKBaseEffect *)effect;
- (void)render;
- (void)update:(float)dt;

@end

And

#import "PSSprite.h"

typedef struct {
    CGPoint geometryVertex;
    CGPoint textureVertex;
} TexturedVertex;

typedef struct {
    TexturedVertex bl;
    TexturedVertex br;    
    TexturedVertex tl;
    TexturedVertex tr;    
} TexturedQuad;

@interface PSSprite()

@property (strong) GLKBaseEffect * effect;
@property (assign) TexturedQuad quad;
@property (strong) GLKTextureInfo * textureInfo;

@end

@implementation PSSprite
@synthesize effect = _effect;
@synthesize quad = _quad;
@synthesize textureInfo = _textureInfo;
@synthesize position = _position;
@synthesize contentSize = _contentSize;
@synthesize moveVelocity = _moveVelocity;

- (id)initWithFile:(NSString *)fileName effect:(GLKBaseEffect *)effect {
    if ((self = [super init])) {  
        // 1
        self.effect = effect;

        // 2
        NSDictionary * options = [NSDictionary dictionaryWithObjectsAndKeys:
                              [NSNumber numberWithBool:YES],
                              GLKTextureLoaderOriginBottomLeft, 
                              nil];

        // 3
        NSError * error;
        NSString *path = [[NSBundle mainBundle] pathForResource:fileName ofType:nil];
        // 4
        self.textureInfo = [GLKTextureLoader textureWithContentsOfFile:path options:options error:&error];
        if (self.textureInfo == nil) {
            NSLog(@"Error loading file: %@", [error localizedDescription]);
            return nil;
        }
        self.contentSize = CGSizeMake(self.textureInfo.width, self.textureInfo.height);
        //Set up Textured Quad
        TexturedQuad newQuad;
        newQuad.bl.geometryVertex = CGPointMake(0, 0);
        newQuad.br.geometryVertex = CGPointMake(self.textureInfo.width, 0);
        newQuad.tl.geometryVertex = CGPointMake(0, self.textureInfo.height);
        newQuad.tr.geometryVertex = CGPointMake(self.textureInfo.width, self.textureInfo.height);

        newQuad.bl.textureVertex = CGPointMake(0, 0);
        newQuad.br.textureVertex = CGPointMake(1, 0);
        newQuad.tl.textureVertex = CGPointMake(0, 1);
        newQuad.tr.textureVertex = CGPointMake(1, 1);
        self.quad = newQuad;

    }
    return self;
}



- (GLKMatrix4) modelMatrix {

    GLKMatrix4 modelMatrix = GLKMatrix4Identity;    
    modelMatrix = GLKMatrix4Translate(modelMatrix, self.position.x, self.position.y, 0);
    modelMatrix = GLKMatrix4Translate(modelMatrix, -self.contentSize.width/2, -self.contentSize.height/2, 0);
    return modelMatrix;

}

- (void)render { 

    // 1
    self.effect.texture2d0.name = self.textureInfo.name;
    self.effect.texture2d0.enabled = YES;

    self.effect.transform.modelviewMatrix = self.modelMatrix;

    // 2    
    [self.effect prepareToDraw];

    // 3
    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);

    // 4
    long offset = (long)&_quad;        
    glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *) (offset + offsetof(TexturedVertex, geometryVertex)));
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *) (offset + offsetof(TexturedVertex, textureVertex)));

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

- (void)update:(float)dt {
    GLKVector2 curMove = GLKVector2MultiplyScalar(self.moveVelocity, dt);
    self.position = GLKVector2Add(self.position, curMove);    
}

@end

I'm not allowed to Dealloc or release anything Because my program is using ARC to automatically handle the memory. 不允许我取消分配或释放任何内容,因为我的程序正在使用ARC自动处理内存。

After debugging and profiling, it shows I have thousands of mallocs with a reference count of +1, coming from: libGFXShared.dylib. 经过调试和分析后,它显示我有数千个malloc,引用计数为+1,来自:libGFXShared.dylib。 The responsible caller is gfxAllocateTextureLevel 负责的呼叫者是gfxAllocateTextureLevel

Found the answer here: Release textures (GLKTextureInfo objects) allocated by GLKTextureLoader 在这里找到答案: 释放由GLKTextureLoader分配的纹理(GLKTextureInfo对象)

Apparently passing the texture to OpenGL puts OpenGL in charge of the memory forcing you to use glDeleteTextures to delete it. 显然将纹理传递给OpenGL将使OpenGL负责内存,迫使您使用glDeleteTextures删除它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM