Utilisation des octets d'une instance NSMutableData tout en lui permettant d'être automatique
-
28-10-2019 - |
Question
J'ai utilisé
NSMutableData* mutableData = [NSMutableData dataWithLength: someLength];
void* bitmapData = [mutableData mutableBytes];
CGContextRef context = CGBitmapContextCreate(bitmapData,...);
// ...use context
CGContextRelease(context);
J'ai une piscine autorease en place, mais quand je regarde cela dans des instruments, mutableData
Cela ne semble pas être traité.
J'ai pensé à utiliser alloc
/init
Comme ci-dessous, mais je ne sais pas si l'envoi release
Purgerait bitmapData
aussi bien.
NSMutableData* mutableData = [[NSMutableData alloc] initWithLength: someLength];
void* bitmapData = [mutableData mutableBytes];
[mutableData release];
//...
Quelle est la bonne façon d'utiliser NSMutableData
ici?
Je pensais utiliser NSMutableData
à la place de malloc()
et free()
Serait pratique car ce sera en autoree. Mais maintenant, je ne sais pas si c'est vrai.
La solution
Quand tu dis mutableData
Cela ne semble pas être traité, voulez-vous dire au moment de CGContextRelease()
, ou voulez-vous dire qu'il ne traite jamais et qu'il fuit chaque fois que vous exécutez cela?
Dans votre premier exemple, vous ne vous attendriez pas mutableData
Pour traiter jusqu'à ce que la piscine Autorelease s'écoule (généralement à la fin de la boucle d'événement), car vous avez utilisé -dataWithLength:
. Dans votre deuxième exemple, il n'est pas défini si mutableData
serait libéré. L'appel à -mutableBytes
Peut appliquer une retenue et une auto-édition pour s'assurer que le pointeur est valide pour le reste de la boucle d'événement (c'est assez courant avec ce type de méthodes), mais les documents ne disent pas, donc votre deuxième exemple est un comportement indéfini si vous utilisez bitmapData
plus tard.
Maintenant si mutableData
fuites, puis vous la retenez probablement ailleurs.
Autres conseils
Demander une instance de nsmutabledata pour ses mutablesBytes renvoie simplement un pointeur vers le tampon existant (déjà alloué) qu'il gère pour vous. Il n'a aucun effet sur la mémoire du point de vue de la gestion.
Ainsi, dans votre premier exemple, le fait que MutableData ne semble pas être traité lorsque vous le regardez dans les instruments pourrait être lié à l'environnement du pool d'autorease à l'époque. Le code utilisant MutableData de cette manière a-t-il un NSAutoreleSelepool en place? Voyez-vous des avertissements dans la console comme "Autorelease appelée sans piscine en place; juste qui fuit"? Si c'est le cas, il vous suffit d'envelopper le code:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// bitmap drawing code here
[pool drain];
Dans le deuxième échantillon, vous pouvez utiliser ALLOC / INIT sur l'instance NSMutableData, mais vous devrez le libérer après avoir terminé en utilisant le pointeur que vous obtenez à MutableBytes. Le pointeur pointera vers la mémoire (libérée) après avoir appelé la libération, et l'accès entraînera le redoutable Exc_Bad_Access.
De plus, l'utilisation de Malloc / Free serait probablement mon premier choix ici, car vous devenez très explicite sur la façon et le moment où la mémoire est allouée et libérée. NSMUTALDATA + AUTORELAISE ne vous achète vraiment rien, sauf quelques frais généraux, si vous n'utilisez l'objet pour autre chose.