【问题标题】:What to do when "memory leaks" are caused by the Foundation framework?当Foundation框架导致“内存泄漏”时怎么办?
【发布时间】:2011-11-02 21:34:08
【问题描述】:

随着时间的推移,我目前正在开发的应用程序正在积累越来越多的内存。这并不是真正的内存泄漏,因为 Leaks 工具不会将其识别为泄漏,但它会不断占用越来越多的内存。

我一直在使用 Instruments(内存分配工具)来找出为什么会发生这种情况,我现在正在制作堆快照,以便找到运行周期中不同点之间的内存差异。似乎在每个循环之后,使用的内存增加了大约 560 KB。

这是 Instruments 工具中的样子:

以及选择CFString行时:

右侧的完整堆栈跟踪如下所示:

   0 CoreFoundation _CFRuntimeCreateInstance
   1 CoreFoundation __CFStringCreateImmutableFunnel3
   2 CoreFoundation CFStringCreateWithBytes
   3 Foundation -[NSString initWithCoder:]
   4 Foundation _decodeObject_old
   5 SyncServices -[ISDProperty initWithCoder:]
   6 SyncServices -[ISDRelationship initWithCoder:]
   7 Foundation _decodeObject_old
   8 Foundation _decodeValueOfObjCType
   9 Foundation -[NSUnarchiver decodeValueOfObjCType:at:]
  10 Foundation -[NSArray(NSArray) initWithCoder:]
  11 Foundation _decodeObject_old
  12 SyncServices -[ISDEntity initWithCoder:]
  13 Foundation _decodeObject_old
  14 Foundation _decodeValueOfObjCType
  15 Foundation -[NSUnarchiver decodeValueOfObjCType:at:]
  16 Foundation -[NSArray(NSArray) initWithCoder:]
  17 Foundation _decodeObject_old
  18 SyncServices -[ISDRelationship initWithCoder:]
  19 Foundation _decodeObject_old
  20 Foundation _decodeValueOfObjCType
  21 Foundation -[NSUnarchiver decodeValueOfObjCType:at:]
  22 Foundation -[NSArray(NSArray) initWithCoder:]
  23 Foundation _decodeObject_old
  24 SyncServices -[ISDEntity initWithCoder:]
  25 Foundation _decodeObject_old
  26 Foundation _decodeValueOfObjCType
  27 Foundation -[NSUnarchiver decodeValueOfObjCType:at:]
  28 Foundation -[NSArray(NSArray) initWithCoder:]
  29 Foundation _decodeObject_old
  30 SyncServices -[ISDRelationship initWithCoder:]
  31 Foundation _decodeObject_old
  32 Foundation _decodeValueOfObjCType
  33 Foundation -[NSUnarchiver decodeValueOfObjCType:at:]
  34 Foundation -[NSArray(NSArray) initWithCoder:]
  35 Foundation _decodeObject_old
  36 SyncServices -[ISDEntity initWithCoder:]
  37 Foundation _decodeObject_old
  38 Foundation _decodeValueOfObjCType
  39 Foundation -[NSUnarchiver decodeValueOfObjCType:at:]
  40 Foundation -[NSArray(NSArray) initWithCoder:]
  41 Foundation _decodeObject_old
  42 SyncServices -[ISDRelationship initWithCoder:]
  43 Foundation _decodeObject_old
  44 Foundation _decodeValueOfObjCType
  45 Foundation -[NSUnarchiver decodeValueOfObjCType:at:]
  46 Foundation -[NSArray(NSArray) initWithCoder:]
  47 Foundation _decodeObject_old
  48 SyncServices -[ISDEntity initWithCoder:]
  49 Foundation _decodeObject_old
  50 Foundation +[NSUnarchiver unarchiveObjectWithData:]
  51 SyncServices -[ISDObjectGraphWrapper initWithCoder:]
  52 Foundation -[NSKeyedPortCoder decodeObjectForKey:]
  53 Foundation -[NSArray(NSArray) initWithCoder:]
  54 Foundation -[NSKeyedPortCoder decodeObjectForKey:]
  55 Foundation -[NSKeyedPortCoder _decodeObjectNoKey]
  56 Foundation -[NSKeyedPortCoder _walkAndDecodeDataWithType:at:chase:invocation:inStructure:]
  57 Foundation decodeInvocationArguments
  58 Foundation -[NSKeyedPortCoder decodeInvocation]
  59 Foundation -[NSKeyedPortCoder decodeObjectForKey:]
  60 Foundation -[NSConnection handleRequest:sequence:]
  61 Foundation -[NSConnection handlePortCoder:]
  62 Foundation -[NSConnection dispatchWithComponents:]
  63 Foundation __NSFireMachPort
  64 CoreFoundation __CFMachPortPerform
  65 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__
  66 CoreFoundation __CFRunLoopDoSource1
  67 CoreFoundation __CFRunLoopRun
  68 CoreFoundation CFRunLoopRunSpecific
  69 Foundation -[NSRunLoop(NSRunLoop) runMode:beforeDate:]
  70 SyncServices -[ISyncConcreteSession _waitForTransitionFromPhase:untilDate:]
  71 SyncServices +[ISyncSession _sessionWithClient:entityNames:beforeDate:clientHasTruthForEntityNames:quietlyPushTruth:target:selector:anchors:hasChanges:skip:error:]
  72 SyncServices +[ISyncSession beginSessionWithClient:entityNames:beforeDate:]
  73 SyncServices -[ISyncConcreteSessionDriver _beginSyncSession:]
  74 SyncServices -[ISyncConcreteSessionDriver _preSync]
  75 SyncServices -[ISyncConcreteSessionDriver _sync:]
  76 SyncServices -[ISyncConcreteSessionDriver sync]
  77 **Our application** - [SLSyncOperation performLocalSync] /Users/andrei/Desktop/MacOSX_Client/osx/Classes/SLSyncOperation.m:94
  78 **Our application** -[SLSyncOperation main] /Users/andrei/Desktop/MacOSX_Client/osx/Classes/SLSyncOperation.m:251
  79 Foundation -[__NSOperationInternal start]
  80 Foundation ____NSOQSchedule_block_invoke_2
  81 libdispatch.dylib _dispatch_call_block_and_release
  82 libdispatch.dylib _dispatch_worker_thread2
  83 libsystem_c.dylib _pthread_wqthread
  84 libsystem_c.dylib start_wqthread

我正在使用 SyncServices 来获取联系信息。我正在使用 ISyncSessionDriver 在某个时间间隔(10 秒,也可以在内存分配图像上看到)检查(同步)新信息。代码如下所示。

SLSyncSessionDriverDataSource *dataSource = [[SLSyncSessionDriverDataSource alloc] initWithManagedObjectModel:managedObjectModel context:managedObjectContext];

ISyncSessionDriver *localDriver = [ISyncSessionDriver sessionDriverWithDataSource:dataSource];
SLSyncSessionDriverDelegate *theDelegate = [[SLSyncSessionDriverDelegate alloc] init];
[localDriver setDelegate:theDelegate];

[theDelegate release];
[dataSource release];    

[localDriver sync];

感谢您能给我的任何帮助!

【问题讨论】:

    标签: objective-c macos memory-management memory-leaks core-foundation


    【解决方案1】:

    假设您发现了一个真正的泄漏点,一些想法:

    • 您只能在可能有新的同步时运行同步 信息(使用 kqueue 或 FSEvents 观察 ~/Library/Application Support/AddressBook 的变化)。

    • 您可以在定期回收的子进程中运行同步,或者按照之前的建议,只需运行一次进程执行同步然后退出。

    同步服务从来没有运行得非常好,并且在 10.7 中已被弃用,所以我想如果有任何额外的工作,它不会有太多的表现。我认为提出一个独立的示例和submit it as a bug 不会浪费时间,尤其是如果它泄漏得这么厉害的话。另外,我建议在地址簿框架上提交另一个错误,说明您希望能够检查/接收新/更新信息的通知。

    【讨论】:

    • 感谢您的回答。 fork(创建子进程)在 OSX 上似乎不太好用,尤其是在使用其他框架的应用程序中。我已经尝试过 FSEvents 并且效果很好。最终,我更好地查看了代码,并发现是一个 instance variable 导致了这种情况。我会一次又一次地为它分配内存而不释放。发布后,它工作正常。有趣的是,XCode 分析器没有将我正在做的事情记录为潜在的内存泄漏。
    • 很高兴你知道了!是的,一旦你在做图形化的东西,你就不能 fork,但是还有其他方法(例如 NSWorkspace 或 Launch Services 是高级的,还有低级的)来启动附属应用程序。在 Lion 上,您还可以查看 XPC 服务。
    猜你喜欢
    • 2011-05-31
    • 2017-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-09
    • 2018-07-27
    • 2015-07-06
    • 2014-06-07
    相关资源
    最近更新 更多