Leaks 在 iPad 上使用 CoreData 报告的真正离奇的数据

Posted

技术标签:

【中文标题】Leaks 在 iPad 上使用 CoreData 报告的真正离奇的数据【英文标题】:Truly bizarre data reported by Leaks using CoreData on iPad 【发布时间】:2010-09-21 03:04:26 【问题描述】:

更新 2: Apple 对我的错误报告的回应是“我们相信这个问题已经在 ios 4.2 b1 (8C5091e) 中得到解决。请让我们知道你是否继续遇到这个问题通过更新此错误报告来获得新发布的软件。”我想这承认问题出在他们的代码中,而不是我的。当我或我认识的人可以更新以尝试此操作时,我会更新结果。

更新:我的同事在另一台电脑和 iPad 上重现了这个问题,所以这可能不仅仅是我的设置问题。

这很奇怪。 我最近注意到 Leaks 工具报告了我的应用程序中的内存泄漏,并且从不指向堆栈跟踪中的代码,只是各种内置库。幸运的是(?)我能够剥离几乎所有东西并最终得到一个愚蠢的简单项目,每次都会触发这种行为,至少在我的机器上是这样。可以肯定的是,我已经开始了一个新项目并完成了这些步骤并遇到了相同的行为。

我在装有 iOS 3.2.2 的 iPad(非 3G)上使用 Xcode 3.2.4 和 Instruments 2.7。

我启动了一个新的“基于窗口的应用程序”,以 iPad 为目标并选中“使用 Core Data 进行存储”框,这会在应用程序委托中为方便的 Core Data 内容生成一组属性访问器。 (如果需要,我可以发布这些内容,但我根本不会更改它们生成的内容。) 我编辑模型以添加一个实体,称为“用户”,没有其他属性或关系。 我向应用程序委托添加了一个-(void)loadUser 方法并在-(BOOL)application:didFinishLaunchingWithOptions: 中调用它

这是唯一的自定义代码,如上所述。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions     
  // Override point for customization after application launch.

  [window makeKeyAndVisible];
  [self loadUser];

  return YES;


- (void)loadUser 
  NSManagedObjectContext *moc = self.managedObjectContext;
  NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
  NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"User"
                                                       inManagedObjectContext:moc];
  [fetchRequest setEntity:entityDescription];

  NSError *error;

  NSLog(@"counting users");
  NSUInteger count = [moc countForFetchRequest:fetchRequest error:&error];
  if (count == NSNotFound) 
    NSLog(@"error: %@", error);
   else if (count == 0) 
    NSLog(@"creating user");
    // make a user
    NSManagedObject *object = [[NSManagedObject alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:moc];
    if (![moc save:&error]) 
      NSLog(@"error: %@", error);
    
    [object release];
  

  NSLog(@"fetching user");
  NSArray *results = [moc executeFetchRequest:fetchRequest error:&error];
  if (results) 
    NSLog(@"results: %@", results);
   else 
    NSLog(@"error: %@", error);
  
  [fetchRequest release]; 

计数和插入是因为如果没有数据就不会发生泄漏,这是我所知道的“填充”它的最简单方法。日志只是为了直接进行完整性检查;它们可以被移除,泄漏仍然会出现。

这段代码对我来说似乎完全无害。当我在带有 Leaks 的设备上运行它时,我让它在几秒钟后自动检查是否有泄漏,并且每次都会出现这个问题:

这不会发生在模拟器上,但总是发生在设备上。

显然这里发生了一些奇怪的事情。 javascript 核心?这在哪里出现?这是其中之一的堆栈跟踪:

16 libSystem.B.dylib thread_assign_default
15 libSystem.B.dylib _pthread_start
14 WebCore RunWebThread(void*)
13 JavaScriptCore JSC::initializeThreading()
12 libSystem.B.dylib pthread_once
11 JavaScriptCore JSC::initializeThreadingOnce()
10 JavaScriptCore WTF::initializeThreading()
 9 JavaScriptCore WTF::initializeMainThread()
 8 JavaScriptCore WTF::initializeMainThreadPlatform()
 7 libobjc.A.dylib objc_msgSend_uncached
 6 libobjc.A.dylib _class_lookupMethodAndLoadCache
 5 libobjc.A.dylib lookUpMethod
 4 libobjc.A.dylib prepareForMethodLookup
 3 libobjc.A.dylib _class_initialize
 2 libobjc.A.dylib _fetchInitializingClassList
 1 libobjc.A.dylib _objc_fetch_pthread_data
 0 libobjc.A.dylib _calloc_internal

堆栈跟踪都没有提到我的代码。我没有做明确的多线程。不涉及 Web 视图或与 JavaScript 相关的任何其他内容。在我的机器上,只要按照上面的步骤,我就一直得到这个结果。我已经在 iPad 上删除并重新安装了该应用程序。我已经重新启动了 Xcode,重新启动了 iPad,并重新启动了我的计算机。同样的交易。

我的问题: 其他人可以重现相同的问题吗? (编辑:一个人在另一台电脑和 iPad 上拥有)

如果不是,我想这是我的配置有一些奇怪的问题,我想知道我能做些什么来解决它。

如果是这样,到底发生了什么?我的代码有问题吗?这不是我应该如何获取对象吗?是来自 Leaks 的误报,还是 Core Data 中的错误?有解决方法吗?我真的很希望能够准确地检测到泄漏,但这很难做到。

【问题讨论】:

【参考方案1】:

这也发生在我身上,也有一个应用程序创建为具有核心数据支持的基于窗口的应用程序。

我使用仪器分析在 iPad 上运行的应用程序得到了完全相同的跟踪......我试图修复泄漏变得疯狂!很高兴知道其他人遇到了这个问题,那么我们将不得不尝试 4.2?

【讨论】:

是的,对my other question 的回复表明,如果我只有一台设备,我将无法真正尝试 4.2 测试版,所以只要这些泄漏保持较小,我就会尝试暂时接受它们。【参考方案2】:

嗯,肯定有一个新线程启动。 pthread 在 Cocoa 和 Foundation 框架的底层使用。 JavaScriptCore 也指向与 webkit 框架相关的东西。

Apple 框架中存在内存泄漏的情况。这里可能就是这种情况。奇怪的是,它不会出现在模拟器中,而只是出现在设备上。

如果您多次执行-(void) loadUser 方法会发生什么。使内存泄漏更大还是由 CoreData 堆栈的初始化造成的?您需要哪些自定义代码来重现泄漏?你需要调用你的-(void) loadUser 方法来获取泄漏吗?

另一个想法:将 CoreData 设置的持久存储类型更改为其他内容,以查看它是否与此相关。如果不保存 MOC,还要检查是否发生内存泄漏。

【讨论】:

我将在多个 cmets 中对此作出回应,因为 cmets 完全无法格式化 afaik。是的,我需要调用 loadUser 来触发泄漏。如上所示,当应用程序完成启动时调用一次。 在这种情况下,如果我设置一个计时器每隔十秒再次调用 loadUser,它在第一次调用后不会泄漏,但在我的原始应用程序中(被大量剥离以结束这个测试用例)每次执行某个操作时它都会泄漏一点。即使这个泄漏是由于不同的原因造成的,我也不希望通过这个定期出现的泄漏来追踪持久性泄漏。 如果我不保存,确实会发生内存泄漏。在这个应用程序中,它会在使用新数据存储启动时创建并保存一个用户,但在随后的每次启动中,loadUser 只获取现有数据而不调用保存,可通过日志输出验证。发生同样的泄漏。 我只是尝试将存储类型更改为 NSBinaryStoreType 而不是 NSSQLiteStoreType(默认值)。发生同样的泄漏。 嗯,在我看来,你应该向苹果提交一个关于这个问题的错误。老实说:它泄漏并不是很好,当然你想要无泄漏的代码,但只要它泄漏这么少字节并且你不能做一些明显的事情来修复它,我会提交一个错误并继续开发。 【参考方案3】:

可能是类似的情况?

https://devforums.apple.com/message/94542

【讨论】:

我在尝试追查时遇到了该线程,但我认为这不是一回事。似乎每个有这个问题的人都是专门得到“GeneralBlock-3584”泄漏的,而我们的要小得多。我的堆栈跟踪也不包括 pthread_create。所以我不能确定这是基于该线程的误报。

以上是关于Leaks 在 iPad 上使用 CoreData 报告的真正离奇的数据的主要内容,如果未能解决你的问题,请参考以下文章

在 ipad 上使用 Coredata 对多列进行全文搜索

在 iPad 设备上测试时如何访问内存泄漏工具?

可以在 iPad 上看到 Core Data 而不运行使用它的应用程序吗?

CoreData iPad 应用程序崩溃

Coredata iPhone 到带有 iCloud 的 iPad/Mac?

如何使用iOS instruments 中的leaks