5

L'applicazione su cui sto lavorando al momento sta accumulando sempre più memoria con il passare del tempo. Non è in realtà una perdita di memoria, dal momento che lo strumento Leaks non lo riconosce come una perdita, ma è qualcosa che continua a prendere sempre più memoria.Cosa fare quando le "perdite di memoria" sono causate dal framework Foundation?

Utilizzo strumenti (strumento di allocazione della memoria) per scoprire perché questo accade, e ora sto facendo le analisi heap per trovare le differenze di memoria tra i diversi punti nel ciclo in esecuzione. Sembra che dopo ogni ciclo, la memoria utilizzata aumenti di circa 560 KB.

Questo è come sembra nello strumento Strumenti:

Instruments initial

E quando si sceglie la riga CFString:

CFString allocation

La piena dello stack dal lato destro sembra this:

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 

Sto utilizzando SyncServices per ottenere informazioni di contatto. Sto usando un ISyncSessionDriver per controllare (sincronizzare) le nuove informazioni ad un certo intervallo di tempo (10 secondi, può essere visto anche sull'immagine di allocazione della memoria). Il codice è simile a questo.

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]; 

Grazie per l'aiuto che potresti darmi!

risposta

2

Supponendo di aver trovato una vera e propria fuga, un paio di idee:

  • È possibile eseguire solo la sincronizzazione quando c'è probabilità di essere nuovo informazioni (attenzione per i cambiamenti nella ~/Library/Application Support/AddressBook con kqueue o FSEvents).

  • È possibile eseguire la sincronizzazione in un processo secondario che si ricicla periodicamente o con il suggerimento precedente, è sufficiente eseguire un'unica sincronizzazione del processo, quindi uscire.

I servizi di sincronizzazione non hanno funzionato molto bene ed è deprecato a partire dal 10.7, quindi immagino che non vedrà molto se un lavoro aggiuntivo. Non penso che sarebbe una perdita di tempo inventare un esempio autonomo e submit it as a bug, specialmente se si perde così tanto. Inoltre, suggerirei di archiviare un altro bug nel framework della Rubrica spiegando che ti piacerebbe poter verificare/ricevere una notifica di informazioni nuove/aggiornate.

+0

Grazie per la risposta. fork (creando un processo figlio) non sembra funzionare molto bene su OSX, specialmente in un'app che usa altri framework. Ho provato FSEvents e questo ha funzionato abbastanza bene. Alla fine ho esaminato meglio il codice e ho capito che si trattava di una * variabile d'istanza * che causava questo. Assegnerei la memoria per questo ancora e ancora senza rilasciare. Dopo averlo rilasciato, funziona perfettamente. È stato interessante notare che l'XCode Analyzer non registrava ciò che stavo facendo come potenziale perdita di memoria. – Andrei

+0

Felice che tu l'abbia capito! Sì, non si può biforcarsi una volta che si stanno facendo cose grafiche, ma ci sono altri modi (ad esempio, NSWorkspace o Launch Services sono di alto livello, ce ne sono di livello inferiore) per avviare applicazioni sussidiarie. Su Lion puoi anche guardare i servizi XPC. –

Problemi correlati