我遇到了一个我似乎无法弄清楚的问题。完成了大量的搜索,尝试了大约50种不同的变化,到目前为止还没有骰子。这是我的困境。
我有3种方法。一个在我的PageView对象加载时被调用,另一个在用户进行更改时被调用,而最后一个在用户离开页面时被调用。
第一种方法:
- (void)captureInitialLinesTexture {
@autoreleasepool {
self.initialLinesTextureCaptured = TRUE;
GLubyte *buffer =(GLubyte *) malloc (1024 * 1024 * 4 * sizeof(GLubyte));
glPixelStorei(GL_PACK_ALIGNMENT,1) ;
glReadPixels(0, 0, 1024, 1024, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
glBindTexture(GL_TEXTURE_2D, [pageTexture name]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1024, 1024, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
NSData __autoreleasing *tempData = [NSData dataWithBytes:buffer length:1024*1024*4*sizeof(GLubyte)];
if (textureData == nil) {
textureData = [self.pageController.notebookDoc newTextureInPage:self.page];
}
[pageTextures addObject:tempData];
if ([pageTextures count] > 5) {
[pageTextures removeObjectAtIndex:0];
}
textureData.textureData = tempData;
textureData.page = self.page;
self.page.texture = textureData;
self.page.lastLineId = [NSNumber numberWithInt:self.pageController.newLineId - 1];
[self.pageController saveNotebookWithUndo:FALSE];
free((GLubyte*)buffer);
}
}
第二种方法:
-(void)capturePageTexture {
@autoreleasepool {
GLubyte *buffer =(GLubyte *) malloc (1024 * 1024 * 4 * sizeof(GLubyte));
glPixelStorei(GL_PACK_ALIGNMENT,1) ;
glReadPixels(0, 0, 1024, 1024, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
NSData __autoreleasing *tempData = [NSData dataWithBytes:buffer length:1024*1024*4*sizeof(GLubyte)];
[pageTextures addObject:tempData];
if ([pageTextures count] > 5) {
[pageTextures removeObjectAtIndex:0];
}
free((GLubyte*)buffer);
}
}
最后一种方法:
-(void)attemptInstantPageTextureCapture {
if ([pageTextures count] > 0) {
self.page.texture.textureData = [pageTextures lastObject];
self.page.lastLineId = [NSNumber numberWithInt:self.pageController.newLineId - 1];
[self.pageController saveNotebookWithUndo:FALSE];
}
[pageTextures removeAllObjects];
pageTextures = [NSMutableArray arrayWithCapacity:0];
}
我的问题是那些NSData * tempData变量。出于某种原因,在我的PageView消失后(通过Allocations Instruments发现),其中一个随机出现。
如果我加载了PageView,则会触发captureInitialLinesTexture。然后,我可以在每次笔画后添加大量笔划和capturePageTexture,在NSMutableArray名称pageTextures中保留最多5个NSData变量。当我离开PageView时,NSMutableArray被清空。
现在,这就是它被撞到墙上的地方。 NSData的分配总是相同的大小,在这种情况下为4mb。当页面加载时,我有1 4mb的分配。如果我做笔画,我可以多达5个。然后,当我离开PageView时,最多5个4mb分配(NSData)被释放,但我总是留下1.如果我然后去仪器上的Call Tree,它从第一个方法或第二个方法随机地说方法。为什么转储存储在数组中的5 NSData没有问题,但由于某种原因,1 NSData在某处保持活动状态。此外,这个神秘的NSData随机来自任何一种方法。
就像我说的那样,我搜索过并找不到解决这个问题的方法。 4MB的内存显然是巨大的,所以任何这种泄漏都会随着时间推移杀死应用程序。
一次尝试的分配:
该尝试的调用树:
另一次尝试的分配:
调用树进行其他尝试:
每次都会触发相同的精确代码,并且每次NSData保持活动时都是随机的。任何人都知道我做错了什么?如果您想知道,“page”和“textureData”变量是NSManagedObjects。就我所尝试的事情而言:
对NSData对象进行alloc,然后调用initWithBytes:length:
initWithBytesNoCopy:长度: - 没有调用free((GLubyte *)缓冲区);
initWithBytesNoCopy:Length:freeWhenDone: - 没有调用free((GLubyte *)缓冲区);
上面两次尝试的NSData类方法版本
不使用@autoreleasepool
不使用__autoreleasing进行var声明
使NSMutableArray pageTextures成为PageView
的属性在弹出NavigationController堆栈之前将PageView设置为nil
使用__strong遍历pageTextures可变数组并将所有NSData设置为nil或null。
如上所述,这一切都发生在一个PageView类中,该类是PageViewController中的一种,它被推入到导航控制器上然后弹出。一旦从导航堆栈中弹出PageViewController(PageView的唯一超级视图),一个随机NSData分配仍然存在。
任何建议都将非常感谢!就上面提到的核心数据元素而言,代码完全按计划工作。唯一的问题是偷偷摸摸的实时NSData分配...... :(
答案 0 :(得分:4)
一段时间后解决了这个问题,但想到我会发布发生的事情以防其他人有同样的问题。基本上问题是NSData对象分配给核心数据实体,核心数据控制它何时释放自己的内存。因此,虽然代码似乎是合理的,但是核心数据仍然保留在NSData对象之后,在它们超出范围并且运行循环结束后(当ARC通常会被踢入时)。
为了解决这个问题,我们只是将NSData保存到文件中,并更改了模型,以便核心数据实体只包含文件路径(NSString)的字符串而不是布尔数据(NSData)。
问题解决了:))
答案 1 :(得分:1)
malloc
在一个线程上分配的内容在另一个线程上释放时不会释放。将您的代码包装在此:
dispatch_async(dispatch_get_main_queue(), ^{
// malloc and whatever other code goes here...
});
答案 2 :(得分:0)
__autoreleasing关键字没有按照您的想法执行。它用于传递包含初始化它们的方法的未初始化指针的指针。然后,这些方法知道不保留它们初始化的值,因为它的唯一目的是返回在调用方法中使用。在这种情况下你不需要它(默认的强大会很好,当它超出范围时它会被释放)。删除该关键字时,错误是否完全相同?