Утечка памяти в блоке @autoreleasepool
Я использую Xcode 4.4 и разрабатываю приложение для iOS 5.1 с ARC. У меня есть поток (кроме основного), который периодически вызывает метод ниже.
- (void)updateLabels:(NSTimeInterval)timeSinceLastUpdate
{
int lastTime = self.time;
self.scoreScale -= ((self.scoreScale-1)/5);
self.time -= timeSinceLastUpdate;
if (self.time <= 0) {
self.time = 0.0;
}
if (lastTime != (int) self.time) {
self.timeChanged = YES;
}
@autoreleasepool {
NSString *timeString = [NSString stringWithFormat:@"%.2d:%.2d",(int)(self.time/60),((int)self.time%60)]; //leak!!!
if (self.scoreScale <=1) self.scoreScale = 1;
GLKBaseEffect *scoreValueEffect = [self.sprites objectForKey:@"score_value"];
if (self.scoreChanged) {
scoreValueEffect = [[ILUtils sharedInstance] makeEffectWithString:[NSString stringWithFormat:@"%@",self.score] alignment:UITextAlignmentLeft fontName:@"WetLetters EFN" fontSize:20 withViewSize:self.view.bounds.size withRect:CGRectMake(935, 50, 100, 30)];
}
scoreValueEffect.transform.modelviewMatrix = [[ILUtils sharedInstance] setupSpriteModelviewMatrixWithViewRect:CGRectMake(955, 46-(30*self.scoreScale-30)/2, 100*self.scoreScale, 30*self.scoreScale)];
[self.sprites setObject:scoreValueEffect forKey:@"score_value"];
if (self.timeChanged) {
GLKBaseEffect *timeValueEffect = [[ILUtils sharedInstance] makeEffectWithString:timeString alignment:UITextAlignmentLeft fontName:@"WetLetters EFN" fontSize:24 withViewSize:self.view.bounds.size withRect:CGRectMake(955, 75, 100, 30)];
[self.sprites setObject:timeValueEffect forKey:@"time_value"];
}
}
}
Когда я использую инструменты, я вижу, что использование памяти увеличивается со временем. Когда я закомментирую строку создания строки, использование памяти стабильно. Я также пытался создать строку с помощью методов alloc & init, но это не помогло. Я нашел похожую ветку в https://stackru.com/questions/ask?title=@autoreleasepool%20not%20working но включение / отключение опции NSZombieEnabled не имеет значения.
Я не могу понять, почему все эти строки не освобождаются, хотя я использую блок @autorelease, как сказано в https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html,
Я что-то пропустил? Благодарю.
// РЕДАКТИРОВАТЬ Материал, вызванный makeEffectWithString
:
- (GLKBaseEffect*)makeEffectWithString:(NSString*)string alignment:(UITextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size withViewSize:(CGSize)viewSize withRect:(CGRect)rect
{
GLKBaseEffect *effect = [[GLKBaseEffect alloc] init];
effect.texture2d0.enabled = YES;
effect.texture2d0.name = [self textureWithString:string dimensions:rect.size alignment:alignment fontName:name fontSize:size].name;
effect.transform.projectionMatrix = [self setupOrthoProjectionMatrixWithViewSize:viewSize];
effect.transform.modelviewMatrix = [[ILUtils sharedInstance] setupSpriteModelviewMatrixWithViewRect:rect];
effect.useConstantColor = YES;
effect.constantColor = GLKVector4Make(0.7f,0.7f,0.7f,0.7f);
return effect;
}
- (GLKTextureInfo*)textureWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(UITextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size
{
UIFont *font = [UIFont fontWithName:name size:size];
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
CGContextRef context = CGBitmapContextCreate(nil, dimensions.width, dimensions.height, 8, dimensions.width, colorSpace, kCGImageAlphaOnly);
CGColorSpaceRelease(colorSpace);
CGContextSetGrayFillColor(context, 1.0, 1.0);
UIGraphicsPushContext(context);
[string drawInRect:CGRectMake(0, 0, dimensions.width, dimensions.height) withFont:font lineBreakMode:UILineBreakModeWordWrap alignment:alignment];
UIGraphicsPopContext();
NSMutableDictionary *options = [NSMutableDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:GLKTextureLoaderOriginBottomLeft];
GLKTextureInfo *texture = [GLKTextureLoader textureWithCGImage:CGBitmapContextCreateImage(context) options:options error:nil];
CGContextRelease(context);
return texture;
}
//РЕДАКТИРОВАТЬ
- (void)drawSpriteUsingEffect:(GLKBaseEffect*)effect
{
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 20, BUFFER_OFFSET(0));
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 20, BUFFER_OFFSET(12));
[effect prepareToDraw];
glDrawArrays(GL_TRIANGLES, 0, 6);
}
1 ответ
Вы можете использовать инструменты Allocations для "Mark Heap". Кажется, в этом есть некоторые инструкции по устранению таких проблем с памятью.