【问题标题】:A simple code that worked fine under GC but started crashing in ARC一个在 GC 下运行良好但在 ARC 中开始崩溃的简单代码
【发布时间】:2012-05-22 08:51:58
【问题描述】:

我有以下简单的“检查我的应用程序是否设置为在登录时启动”代码。它在垃圾收集下运行良好。但是,由于我开始使用 ARC(并根据需要插入“__bridge”),代码开始随机且不可预测地崩溃。根据堆栈跟踪,代码在某些CFRelease 期间崩溃。任何想法可能导致在 ARC 下发生这种情况?

- (BOOL)loginItemExists
{
  NSString *appPath = [[NSBundle mainBundle] bundlePath];
  LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL,
                                     kLSSharedFileListSessionLoginItems, NULL);
  BOOL found = NO;  
  UInt32 seedValue;
  CFURLRef thePath;
  CFArrayRef loginItemsArray = LSSharedFileListCopySnapshot(loginItems,
                                                              &seedValue);
  for (id item in (__bridge NSArray *)loginItemsArray)
  {    
    LSSharedFileListItemRef itemRef = (__bridge LSSharedFileListItemRef)item;
    if (LSSharedFileListItemResolve(itemRef, 0, &thePath, NULL) == noErr)
    {
      if ([[(__bridge NSURL *)thePath path] hasPrefix:appPath])
        found = YES;
    }

    //docs for LSSharedFileListItemResolve say we should release the CFURLRef
    if (thePath != NULL)
      CFRelease(thePath);

    if (found)
      break;
  }

  CFRelease(loginItemsArray);
  CFRelease(loginItems);
  return found;
}

【问题讨论】:

    标签: objective-c cocoa memory-management automatic-ref-counting


    【解决方案1】:

    如果该项目未解决,您将在第二次循环中获得双重释放。在开始时以及在释放它之后将 thePath 设置为 nil,这将修复崩溃。

    【讨论】:

    • 你会说我的if (thePath != NULL) 支票是不必要的吗?我的意思是,CFRelease(NULL) 是否允许?如果是,我的检查可能是不必要的。
    • CFRelease 的参数不能为NULL,需要测试。
    【解决方案2】:

    您可以通过将编译器标志 -fno-objc-arc 添加到特定文件来禁用 ARC

    【讨论】:

    • 感谢您的建议。但是,在这种情况下,我宁愿不禁用 ARC,而是尝试了解问题出在哪里。
    • 此外,ARC 也没有管理任何东西,因为我正在做常规的__bridge。这似乎意味着在手动内存管理下会出现同样的问题。问题似乎是 GC -> non-GC 转换引入了问题。不是 ARC 本身。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-26
    • 2020-08-18
    相关资源
    最近更新 更多