2 votes

Utiliser les octets d'une instance de NSMutableData tout en lui permettant d'être libérée automatiquement

J'ai utilisé

NSMutableData* mutableData = [NSMutableData dataWithLength: someLength];
void* bitmapData = [mutableData mutableBytes];
CGContextRef context = CGBitmapContextCreate(bitmapData,...);
// ...use context
CGContextRelease(context);

J'ai mis en place un pool de libération automatique, mais lorsque j'examine cette question dans les instruments, je constate qu'il n'y a pas d'autre solution, mutableData ne semble pas être désalloué.
J'ai pensé à utiliser alloc / init comme ci-dessous, mais je ne sais pas si le fait d'envoyer des release purgerait bitmapData également.

NSMutableData* mutableData = [[NSMutableData alloc] initWithLength: someLength];
void* bitmapData = [mutableData mutableBytes];
[mutableData release];
//...

Quelle est la bonne façon d'utiliser NSMutableData ici ?

Je pensais que l'utilisation de NSMutableData au lieu de malloc() y free() Ce serait pratique parce qu'il sera distribué automatiquement, mais maintenant je ne suis pas sûr que ce soit vrai.

1voto

Rob Napier Points 92148

Lorsque vous dites mutableData ne semble pas être désalloué, est-ce que vous voulez dire au moment de la création de CGContextRelease() ou voulez-vous dire qu'il n'y a jamais de désallocation et qu'il y a des fuites à chaque fois que vous exécutez ce programme ?

Dans votre premier exemple, vous ne vous attendez pas à ce que mutableData de désallouer jusqu'à ce que le pool d'autorelease se vide (généralement à la fin de la boucle d'événements), parce que vous avez utilisé la fonction -dataWithLength: . Dans votre deuxième exemple, il n'est pas défini si mutableData serait libéré. L'appel à -mutableBytes pourrait appliquer un retain et un autorelease pour s'assurer que le pointeur est valide pour le reste de la boucle événementielle (c'est assez courant avec ce genre de méthodes), mais la documentation ne le dit pas, donc votre deuxième exemple est un comportement non défini si vous utilisez bitmapData plus tard.

Maintenant, si mutableData il est probable qu'il y ait une surconsommation ailleurs.

0voto

lyricsboy Points 1776

Demander à une instance de NSMutableData ses mutableBytes renvoie simplement un pointeur sur le tampon existant (déjà alloué) qu'elle gère pour vous. Cela 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 désalloué lorsqu'on le regarde dans Instruments pourrait être lié à l'environnement du pool autorelease à ce moment-là. Le code qui utilise mutableData de cette manière a-t-il un NSAutoreleasePool en place ? Voyez-vous des avertissements dans la console comme "autorelease called with no pool in place ; just leaking" ? Si c'est le cas, il vous suffit d'envelopper le code dans un NSAutoreleasePool :

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// bitmap drawing code here
[pool drain];

Dans le deuxième exemple, vous pourriez utiliser alloc/init sur l'instance NSMutableData, mais vous devriez la libérer après avoir utilisé le pointeur que vous obtenez de mutableBytes. Le pointeur pointera sur de la mémoire désallouée (libérée) après l'appel à release, et l'accès à cette mémoire entraînera le redoutable EXC_BAD_ACCESS.

Aussi, l'utilisation de malloc/free serait probablement mon premier choix ici, puisque vous pouvez être très explicite sur comment et quand la mémoire est allouée et libérée. NSMutableData + autorelease ne vous apporte rien d'autre qu'une certaine surcharge, si vous n'utilisez pas l'objet pour autre chose.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X