【问题标题】:AutoreleasePool not catching breakpoints, no warnings, no reporting in Instruments LeaksAutoreleasePool 没有捕获断点,没有警告,没有在 Instruments Leaks 中报告
【发布时间】:2012-12-19 16:17:42
【问题描述】:

如果没有自动释放池,我会尝试捕捉场景。
这是我的测试应用。

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    [self performSelectorInBackground:@selector(bgOperation:) withObject:nil];
}

- (void)bgOperation:(id)obj
{
    NSString *string [[[NSString alloc] init] autorelease];
}

我已尝试设置断点 objc_autoreleaseNoPool。
我已经尝试使用 Instruments / Leaks 进行分析。
OSX 10.7.5 XCode 4.3.3 以 10.6 为目标,AutomaticRefCounting = NO,GarbageCollection = 不支持。

我了解 NSApplication 包含它自己的自动释放池。但我的理解是每次调用 performSelectorInBackground: 都需要它自己的自动释放池。

建议更新:
我试过这个..
在 main.m 中,没有运气。

int main(int argc, char *argv[])
{
    NSString *junk = [[[NSString alloc]init]autorelease];
    return NSApplicationMain(argc, (const char **)argv);
}

还有这个..
在我的 appDelegate 中,也没有结果。

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    [NSThread detachNewThreadSelector:@selector(bgOperation:)
                             toTarget:self
                           withObject:nil];
}

还有这个..
在我的 main.m 中使用 pthreads

void *doJunk(void *ptr){
  NSString *junk = [[[NSString alloc]initWithString:@"string with no pool"]autorelease];
  NSLog(@"%@", junk);
  pthread_exit(NULL);
}

int main(int argc, char *argv[])
{
  pthread_t thread;
  pthread_create(&thread, NULL, doJunk, NULL);
  return NSApplicationMain(argc, (const char **)argv);
}

我了解由于操作系统级别的原因,可能没有任何泄漏(仍未确认),但是当我以 10.6 为目标时,我在日志中看到许多“无池”消息。如果它只是由于操作系统级别而泄漏,那么当我的目标是 10.6 但使用 10.7 SDK 时,我需要一种方法在 10.7 中捕获这些场景。

【问题讨论】:

  • 您是否在日志中查找过“刚刚泄漏”的消息?
  • 只有在运行应用程序并在 10.6 中观看控制台时才能看到它们。

标签: objective-c xcode cocoa memory-management


【解决方案1】:

performSelectorInBackground: 现在可能正在使用 dispatch_queue,它会自动为您设置一个自动释放池。尝试直接启动一个新的 NSThread,看看是否会导致泄漏。

您也可以尝试将代码移至 NSApplicationMain 之前,这将具有相同的行为。

【讨论】:

  • 我读过的所有文档都解释说每次调用 performSelectorInBackgroud: 都需要它自己的自动释放池。这仅适用于某些操作系统级别吗?
  • 这曾经是真的,但我认为它可能已经改变了。
  • [NSThread detachNewThreadSelector:@selector(bgOperation:) toTarget:self withObject:nil];没有效果。
  • 您没有看到消息的原因似乎是事情没有泄漏。直接尝试 pthreads 怎么样?
【解决方案2】:

根据documentation,在这种情况下仍然必须创建一个池。

performSelectorInBackground:withObject: 方法创建一个新的分离线程,并使用指定的方法作为新线程的入口点。

[...]

调用该方法的效果与调用NSThread的detachNewThreadSelector:toTarget:withObject:方法的效果是一样的,以当前对象、选择器和参数对象为参数。使用默认配置立即生成新线程并开始运行。在选择器内部,您必须像配置任何线程一样配置线程。例如,您需要设置一个自动释放池(如果您没有使用垃圾回收)并配置线程的运行循环(如果您打算使用它)。

然后根据NSThreaddocumentation

+ (void)detachNewThreadSelector:(SEL)aSelector
                       toTarget:(id)aTarget
                     withObject:(id)anArgument

对于非垃圾收集应用程序,方法 aSelector负责为新分离的线程设置自动释放池,并在该池退出之前释放该池。

因此,除非 Apple 在没有记录的情况下更改实现(非常不可能),否则对于在使用 autorelease 的单独线程中执行的任何选择器,创建池仍然是强制

为了验证文档是否在陈述事实,请尝试替换您的电话

[self performSelectorInBackground:@selector(bgOperation:) withObject:nil];

[NSThread detachNewThreadSelector:@selector(bgOperation:) toTarget:self withObject:nil];

根据文档,上述两个调用应该是等效的。你可能会发现它们不是。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-03
    • 1970-01-01
    • 1970-01-01
    • 2012-06-09
    • 1970-01-01
    • 2021-12-05
    • 1970-01-01
    相关资源
    最近更新 更多