développement iPhone: pointeur être libérés n'a pas été alloué
j'ai eu ce message à partir du débogueur:
Pixture(1257,0xa0610500) malloc: *** error for object 0x21a8000: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
j'ai donc fait un peu de traçage et a obtenu:
(gdb) shell malloc_history 1257 0x21a8000
ALLOC 0x2196a00-0x21a89ff [size=73728]: thread_a0610500 |start | main | UIApplicationMain | GSEventRun | GSEventRunModal | CFRunLoopRunInMode | CFRunLoopRunSpecific | __CFRunLoopDoObservers | CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) | CA::Transaction::commit() | CA::Context::commit_transaction(CA::Transaction*) | CALayerDisplayIfNeeded | -[CALayer _display] | CABackingStoreUpdate | backing_callback(CGContext*, void*) | -[CALayer drawInContext:] | -[UIView(CALayerDelegate) drawLayer:inContext:] | -[AvatarView drawRect:] | -[AvatarView overlayPNG:] | +[UIImageUtility createMaskOf:] | UIGraphicsGetImageFromCurrentImageContext | CGBitmapContextCreateImage | create_bitmap_data_provider | malloc | malloc_zone_malloc
et je ne comprends vraiment pas ce que je fais de mal. voici le code de la [UIImageUtility createMaskOf:]
fonction:
+ (UIImage *)createMaskOf:(UIImage *)source {
CGRect rect = CGRectMake(0, 0, source.size.width, source.size.height);
UIGraphicsBeginImageContext(CGSizeMake(source.size.width, source.size.height));
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0, source.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
UIImage *original = [self createGrayCopy:source];
CGContextRef context2 = CGBitmapContextCreate(NULL, source.size.width, source.size.height, 8, 4 * source.size.width,
CGColorSpaceCreateDeviceRGB(), kCGImageAlphaNoneSkipLast);
CGContextDrawImage(context2, CGRectMake(0, 0, source.size.width, source.size.height), original.CGImage);
CGImageRef unmasked = CGBitmapContextCreateImage(context2);
const float myMaskingColorsFrameColor[6] = { 1,256,1,256,1,256 };
CGImageRef mask = CGImageCreateWithMaskingColors(unmasked, myMaskingColorsFrameColor);
CGContextSetRGBFillColor (context, 256,256,256, 1);
CGContextFillRect(context, rect);
CGContextDrawImage(context, rect, mask);
UIImage *whiteMasked = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return whiteMasked;
}
l'autre fonction personnalisée appelée avant que est la suivante:
- (UIImage *)overlayPNG:(SinglePart *)sp {
NSLog([sp description]);
//Rect and context setup
CGRect rect = CGRectMake(0, 0, sp.image.size.width, sp.image.size.height);
NSLog(@"%f x %f", sp.image.size.width, sp.image.size.height);
//Create an image of a color filled rectangle
UIImage *baseColor = nil;
if (sp.hasOwnColor) {
baseColor = [UIImageUtility imageWithRect:rect ofColor:sp.color];
} else {
SinglePart *facePart = [editingAvatar.face.partList objectAtIndex:0];
baseColor = [UIImageUtility imageWithRect:rect ofColor:facePart.color];
}
//Crete the mask of the layer
UIImage *mask = [UIImageUtility createMaskOf:sp.image];
mask = [UIImageUtility createGrayCopy:mask];
//Create a new context for merging the overlay and a mask of the layer
UIGraphicsBeginImageContext(CGSizeMake(sp.image.size.width, sp.image.size.height));
CGContextRef context2 = UIGraphicsGetCurrentContext();
//Adjust the coordinate system so that the origin
//is in the lower left corner of the view and the
//y axis points up
CGContextTranslateCTM(context2, 0, sp.image.size.height);
CGContextScaleCTM(context2, 1.0, -1.0);
//Create masked overlay color layer
CGImageRef MaskedImage = CGImageCreateWithMask (baseColor.CGImage, mask.CGImage);
//Draw the base color layer
CGContextDrawImage(context2, rect, MaskedImage);
//Get the result of the masking
UIImage* overlayMasked = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIGraphicsBeginImageContext(CGSizeMake(sp.image.size.width, sp.image.size.height));
CGContextRef context = UIGraphicsGetCurrentContext();
//Adjust the coordinate system so that the origin
//is in the lower left corner of the view and the
//y axis points up
CGContextTranslateCTM(context, 0, sp.image.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
//Get the result of the blending of the masked overlay and the base image
CGContextDrawImage(context, rect, overlayMasked.CGImage);
//Set the blend mode for the next drawn image
CGContextSetBlendMode(context, kCGBlendModeOverlay);
//Component image drawn
CGContextDrawImage(context, rect, sp.image.CGImage);
UIImage* blendedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGImageRelease(MaskedImage);
return blendedImage;
}
Vous devez vous connecter pour publier un commentaire.
J'ai eu le même problème, avec un grand nombre des mêmes symptômes:
Si je change la cible de construction à 3.1, les erreurs dans le simulateur de s'en aller. Si j'exécute le code sur l'appareil, les erreurs n'apparaissent pas. Probablement un bug dans la version 3.0
Mon conseil est de tester avec 3.1 sur votre cible, et si vous le souhaitez, vous pouvez créer pour la 3.0 pour la sortie et vous inquiétez pas sur les erreurs qu'ils ne se produisent pas sur l'appareil.
Il semble que vous avez une corruption de la mémoire bug, et il n'est probablement pas dans ce code. Corrompu de la mémoire, des bugs sont ma deuxième plus amusant de bugs, en partie parce qu'ils sont souvent non-déterministe, et les symptômes (aka les accidents) se produisent habituellement longtemps après le réel bug frappé.
Il existe deux principaux types de mémoire bugs:
Dans ce cas, il semble que vous êtes en libérant de trop, ce qui est le plus facile de cas pour voir (b/c il peut tomber en panne plus tôt), mais le plus difficile à traquer.
Ici est une stratégie que vous pouvez utiliser pour vous aider à trouver un supplément de deallocations:
Idéalement, vous pouvez trouver un seul de libération de la mémoire de commande qui, lorsqu'on l'enlève, permettra à votre code fonctionne correctement. Il pourrait être utile d'essayer une recherche binaire approche, si pratique pour votre base de code. Si c'est une grosse base de code, j'espère que vous êtes en utilisant le contrôle de version et vous pouvez essayer de se concentrer sur la récente diff.
Gardez à l'esprit que deallocations peut être invoquée dans plusieurs façons différentes ici. Très probablement, vous êtes à l'appel de
release
etautorelease
sur les objets. Il est également possible que vous pourriez être explicitement appeldealloc
(ce qui est une erreur, tout de même). Et bien sûr, vous pourriez même être en appelant explicitementfree
directement.Une fois que vous avez réussi à se débarrasser de l'extra deallocations, c'est une bonne idée de vérifier pour les fuites de mémoire (aka les affectations supplémentaires). Vous pouvez le faire en utilisant des Instruments et d'autres outils. Un bon endroit pour commencer est par la lecture de Rechercher Les Fuites De Mémoire dans le développement iPhone guide.
Ajouté: C'est aussi une bonne idée de définir un pointeur vers
nil
droit après que vous avez relâché et on y fait de l'utiliser. De cette façon, si vous appelez[objectPtr release];
plus tard, il ne fera rien.(PS Btw, mon #1 plus de plaisir bug est de type corruption de mémoire dans le mutlithreaded code. J'ai eu un de ceux une fois dans un de plusieurs millions de ligne de code à la base).
Bien que probablement pas la cause de votre accident, vous êtes une fuite de mémoire en ne publiant pas la
context2
,unmasked
, etmask
Fondement de Base d'objets à l'aideCFRelease()
,CFImageRelease()
, ou similaire.J'ai eu le même problème avec le code suivant.
J'ai pris la fonction de l'open source Twitterfon app.
Quand j'ai essayé de résoudre le problème, j'ai essayé de changer la dernière ligne de
Et qui a arrêté les messages d'erreur dans la console. Je vais vérifier cela dans les Fuites bientôt pour voir ce qui se passe.
Je voulais juste confirmer, encore une fois, que j'ai eu a été d'obtenir:
erreur et il s'en alla si je change de cible: l'os 3.1, par opposition à 3.0
UIGraphicsGetImageFromCurrentImageContext()
est censé renvoyer un autoreleased UIImage, mais il semble être à double autoreleasing, SEULEMENT dans la version 3.0 simulateur et SEULEMENT avec Xcode 3.2J'ai lutté avec le même message d'erreur dans mon code. Ce que j'étais perplexe, c'est que mon application travaillé en OS 3.0 sans aucun problème jusqu'à ce que j'ai fait une modification mineure à un code qui n'a rien à voir avec la CGImage* trucs. Mais une fois qu'il a commencé à échouer, alors elle n'a jamais travaillé sans s'écraser. Quand je suis passé à 3,1, tout a fonctionné à nouveau. J'ai rétréci vers le bas à l'erreur, à une CGImageRelease() de l'appel. Soit en retirant la ligne ou l'ajout d'un à conserver sur la UIImage résolu le problème--bien que ce n'est pas une solution, car l'application va être une fuite de mémoire.
J'ai essayé d'utiliser NSZombie avec les instruments. Ce n'est pas de l'aide, l'application s'est écrasé sans zombies être détecté.
En outre, Apple exemple des applications (comme TheElements) ne se bloque PAS mais utilise exactement le même code que mon application. Donc, j'ai du mal à accepter le problème réside dans le Cadres de. Pour l'instant, je suis de commutation à 3.1 et aller de l'avant.
Il pourrait être juste moi, mais vous ne pouvez pas effectuer les opérations suivantes ?
whiteMasked est alloué sur la pile de la fonction et après il retourne le pointeur n'est plus valide? Ou ai-je raté quelque chose? Si vous utilisez le retour de l'UIImage* il n'est pas garanti d'être encore là. (il serait hasardeux). N'avez-vous pas besoin d'affecter une UIImage* et puis autorelease avant de retourner?
whiteMasked
est valable au moins jusqu'à ce que l'autorelease pool est vide, ce qui ne sera pas jusqu'à la fin de la boucle des événements. C'est bien d'être utilisés dans cette fonction et c'est bien de retour, trop. Nous voudrions seulement besoin de faire une copie si nous avions prévu d'enregistrer et d'utiliser la même image plus tard (par exemple, dans une variable d'instance).