Objective-C block未发布,仅用于后台应用
我有一个只在后台运行的应用程序(通过在info.plist文件中指定Objective-C block未发布,仅用于后台应用,objective-c,memory-leaks,user-input,objective-c-blocks,background-application,Objective C,Memory Leaks,User Input,Objective C Blocks,Background Application,我有一个只在后台运行的应用程序(通过在info.plist文件中指定LSBackgroundOnly)。 问题是,我在并行队列上运行的所有块都没有被释放。 代码在内存管理的环境中执行-不涉及GC (简化的)代码如下所示。Blubber只是一个虚拟类,它保存一个NSDate用于测试。此外,它还会覆盖retain、release和dealloc以进行一些日志记录: NSOperationQueue *concurrentQueue = [[NSOperationQueue alloc] init];
LSBackgroundOnly
)。
问题是,我在并行队列上运行的所有块都没有被释放。
代码在内存管理的环境中执行-不涉及GC
(简化的)代码如下所示。Blubber只是一个虚拟类,它保存一个NSDate用于测试。此外,它还会覆盖retain
、release
和dealloc
以进行一些日志记录:
NSOperationQueue *concurrentQueue = [[NSOperationQueue alloc] init];
[concurrentQueue setMaxConcurrentOperationCount:NSOperationQueueDefaultMaxConcurrentOperationCount];
Blubber *aBlubber = [[Blubber alloc] init];
aBlubber.aDate = [NSDate date];
[concurrentQueue addOperationWithBlock:^{
NSAutoreleasePool *blockPool = [[NSAutoreleasePool alloc] init];
NSDate *test = [aBlubber aDate];
NSLog(@"Block DONE");
[blockPool release];
}];
[aBlubber release];
[concurrentQueue release];
如果我将应用程序更改为普通(即非backgound)应用程序,我可以观察通过UI进行任何输入时释放的块(即使将焦点更改为另一个窗口也足够)。
由于我的backgorund应用程序直接通过HID USB驱动程序接收输入,并且没有窗口或菜单栏,因此不会发生这种情况
有没有办法手动强制运行循环或其他负责通知队列释放完成的块的方法
(块保留的所有其他对象也不会释放,从而造成巨大的内存泄漏。这些泄漏无法通过泄漏或对象分配工具发现,但可以使用top观察到内存消耗急剧上升。)一个常见的“问题”对于自动释放池来说,如果应用程序正在构建内存而没有接收事件,则最外层的池(由事件循环管理的池)将不会被耗尽
我认为这不适用于这里,因为你正在管理自己的游泳池。。。但为了以防万一,您可以尝试以下方法:
...
//When no events are coming in (i.e. the user is away from their computer), the runloop doesn't iterate, and we accumulate autoreleased objects
[[NSTimer scheduledTimerWithTimeInterval:60.0f target:self selector:@selector(kickRunLoop:) userInfo:nil repeats:YES] retain];
...
- (void) kickRunLoop:(NSTimer *)dummy
{
// Send a fake event to wake the loop up.
[NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined
location:NSMakePoint(0,0)
modifierFlags:0
timestamp:0
windowNumber:0
context:NULL
subtype:0
data1:0
data2:0]
atStart:NO];
}
看起来您正在使用基于堆栈的块,该块在超出范围后使用。需要复制块。如果代码更改为以下内容,则该代码应能正常工作:
[concurrentQueue addOperationWithBlock:[[^{
NSAutoreleasePool *blockPool = [[NSAutoreleasePool alloc] init];
NSDate *test = [aBlubber aDate];
NSLog(@"Block DONE");
[blockPool release];
}copy]autorelease]];
请看这篇文章,了解关于块的完整写操作:您是否尝试过使用C函数(libDispatch)而不是NSOperations?我认为它会产生相同的结果,因为NSBlockOperation被记录为在内部使用libDispatch。谢谢你的建议,无论如何,我会尽快试一试。谢谢你的建议。不过,我非常确定,当我使用addOperationWithBlock时,包装块的NSBlockOperation负责将块传输到适当的存储器。我的问题不是块不执行或行为异常;我的问题是,如果应用程序没有UI,即使它已被放入自动释放池,块仍会继续占用内存。我仍在试验,但似乎@Catfish_-Man的答案恰到好处。