2010-01-27 4 views
2

J'ai la méthode d'instance suivante (adapté de Listing 3-6 de la section Gestion de l'événement dans le Guide de programmation d'applications iPhone):Comment puis-je libérer() après malloc() lorsque le résultat de malloc() est renvoyé par la fonction?

- (CGPoint)originOfTouch:(UITouch *)touch 
{ 
    CGPoint *touchOriginPoint = (CGPoint *)CFDictionaryGetValue(touchOriginPoints, touch); 
    if (touchOriginPoint == NULL) 
    { 
     touchOriginPoint = (CGPoint *)malloc(sizeof(CGPoint)); // leaks 
     CFDictionarySetValue(touchOriginPoints, touch, touchOriginPoint); 
     *touchOriginPoint = [touch locationInView:touch.view]; 
    } 
    return *touchOriginPoint; 
} 

Chaque fois que dans un certain temps mon application fuites 16 octets par suite de l'appel à malloc(). Je ne suis pas sûr comment retourner touchOriginPoint tandis que free() il aussi bien.

Répondre

3

Si vous ne vous souciez pas de légère perte de performance, utilisez un NSMutableDictionary et stocker le point comme NSValue:

NSValue* touchOriginPointValue = [touchOriginPoints objectForKey:touch]; 
if (touchOriginPointValue == nil) { 
    touchOriginPointValue = [NSValue valueWithCGPoint:[touch locationInView:touch.view]]; 
    [touchOriginPoints setObject:touchOriginPointValue forKey:touch]; 
} 
return [touchOriginPointValue CGPointValue]; 

Si vous devez utiliser l'approche CFDictionary, vous devez trouver un placer à free ces malloc mémoire -ed lorsque les valeurs ne sont pas nécessaires. Par conséquent, vous devez transmettre les valeurs callbacks lors de la création du dictionnaire

static void free_malloced_memory (CFAllocatorRef allocator, const void *value) { 
    free((void*)value); 
} 
static const CFDictionaryValueCallBacks values_callbacks = {0, NULL, free_malloced_memory, NULL, NULL}; 
... 
touchOriginPoints = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, & values_callbacks); 
... 
+0

Merci KennyTM, je vais donner à ces fonctions de rappel un coup de feu. –

+0

CFDictionary est requis car UITouch n'implémente pas NSCopying. Lors de l'implémentation de la fonction de rappel, cela n'élimine pas toutes les fuites de mémoire associées. –

+0

@Shaun: Ah c'est vrai. Mais puisque la copie est le seul problème, vous pouvez toujours utiliser 'CFDictionary' avec' UITouch' comme clé, 'NSValue' comme valeurs, et utiliser les callbacks de valeur' & kCFTypeDictionaryValueCallBacks' pour que CF puisse suivre automatiquement le comptage ref. – kennytm

1

Si vous devez renvoyer la valeur malloc'd de la fonction, vous avez transféré la responsabilité de libérer la mémoire à la fonction appelante ou à l'un de ses appelants.

Puisque nous ne pouvons pas voir les fonctions d'appel, nous ne pouvons plus diagnostiquer.

0

Si vous allez retourner un objet qui est alloué, alors vous devez avoir l'appelant free(), ou bien vous devez utiliser une sorte de garbage collection (pour qu'il soit libéré automatiquement).

+0

2 secondes derrière ma réponse ...: D –

+1

Il n'y a pas de GC dans iPhoneOS. – kennytm

+0

Il est très triste qu'il n'y a pas de GC dans iPhoneOS. Je réalise que c'est un commentaire spécifique à l'iPhone, mais ma réponse est générale. – vy32

0

vous ne revenez pas en fait un pointeur, la valeur est copiée à une valeur de température quand il est retourné, de sorte que vous n'êtes pas vraiment restituez le allocation du tout, le problème est que vous ne le libérez pas non plus, vous ajoutez l'allocation au dictionnaire et laissez-le là?

est là comme une fonction EndOfTouch? où vous supprimez le toucher du dictionnaire? s'il y a, appelez gratuitement sur votre allocation là et vous devriez être bien

+0

Il existe une méthode touchEnded dans laquelle je libère ces allocations, mais je constate que lorsque le délégué tactile est supprimé, cette méthode n'est jamais déclenchée, ce qui entraîne des allocations orphelines. –

+0

hmm, comment le délégué tactile est-il supprimé? (Je ne suis pas trop familier avec iphone ou objC d'ailleurs). pourriez-vous parcourir votre liste et tout libérer alors? En dehors de cela, pourriez-vous avoir un dictionnaire d'objets réels, plutôt qu'un dictionnaire de pointeurs ?, (je ne sais pas comment le CFDictionaryGetValue retournerait s'il ne pouvait pas trouver la réponse ...) serait pas d'allocations à libérer. – matt