rozwój iPhone ' a: uwolnienie wskaźnika nie zostało przydzielone

Dostałem wiadomość z debuggera:

Pixture(1257,0xa0610500) malloc: *** error for object 0x21a8000: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug

Więc trochę namierzyłem i dostałem:

(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

I naprawdę nie mogę zrozumieć, co robię źle. oto kod funkcji [UIImageUtility createMaskOf:]:
+ (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;
}

Inna funkcja niestandardowa wywołana wcześniej jest następująca:

- (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;
}
Author: Community, 2009-09-14

7 answers

Miałem ten sam problem, z wieloma tymi samymi objawami:

  • zwalnianie wskaźnika nie było przydzielane błąd
  • uaktualniony do Xcode 3.2
  • błąd w kodzie dla obrazów

Jeśli zmienię cel budowania na 3.1, błędy w symulatorze znikną. Jeśli uruchomię kod na urządzeniu, błędy nie pojawią się. Prawdopodobnie błąd w 3.0

Radzę przetestować z 3.1 jako celem, a jeśli chcesz, możesz zbudować dla 3.0 do wydania i nie martwić się o błędach, ponieważ nie zdarzają się na urządzeniu.

 27
Author: nevan king,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-28 08:54:52

Wygląda na to, że masz uszkodzony błąd pamięci i prawdopodobnie nie ma go w tym kodzie. Uszkodzone błędy pamięci są moim drugim najbardziej zabawnym błędem, częściowo dlatego, że często nie są deterministyczne, a objawy (aka awarie) zwykle zdarzają się długo po rzeczywistym trafieniu błędu.

Istnieją dwa główne typy błędów pamięci:

    / Align = "left" / Uwalniasz więcej niż ty.

W tym przypadku wygląda na to, że ty też się uwalniasz dużo, co jest łatwiejsze do zobaczenia (b / c może upaść wcześniej), ale trudniej wyśledzić.

Oto strategia, której możesz użyć, aby pomóc znaleźć dodatkowe deallokacje:

  • Wyłącz niektóre z Twoich deallocations.
  • sprawdź, czy wypadek nadal ma miejsce.

Najlepiej jest znaleźć jedno polecenie dealokacji, które po usunięciu pozwoli na poprawne działanie kodu. Może być przydatne wypróbowanie metody wyszukiwania binarnego, jeśli jest to praktyczne dla twojej bazy kodowej. Jeśli jest to duża baza kodowa, mam nadzieję, że używasz kontroli wersji i możesz spróbować skupić się na ostatnich diffach.]}

Należy pamiętać, że dealokacje mogą być wywoływane na kilka różnych sposobów. Najprawdopodobniej wywołujesz release i autorelease na obiektach. Możliwe jest również, że jawnie wywołujesz dealloc (co zwykle jest jednak błędem). I oczywiście możesz nawet bezpośrednio wywoływać free.

Gdy pozbędziesz się dodatkowych dealokacji, to dobrze pomysł, aby również sprawdzić wycieki pamięci (aka dodatkowe alokacje). Możesz to zrobić za pomocą instrumentów i innych narzędzi. Warto zacząć od przeczytania znajdowania wycieków pamięci w przewodniku rozwoju iPhone ' a.

Dodano: dobrym pomysłem jest również ustawienie wskaźnika na nil zaraz po jego wydaniu i zakończeniu korzystania z niego. W ten sposób, jeśli zadzwonisz [objectPtr release]; później, to nic nie da.

(PS Btw, mój # 1 Najbardziej zabawny typ błędu to uszkodzenie pamięci w kodzie mutlithreaded. Miałem taki kiedyś w bazie wielomilionowej.)

 22
Author: Tyler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-15 18:09:46

Chociaż prawdopodobnie nie jest to przyczyna twojego wypadku, wyciekasz pamięć, nie wypuszczając context2, unmasked, i mask podstawowe obiekty Fundacji za pomocą CFRelease(), CFImageRelease(), albo coś podobnego.

 3
Author: Brad Larson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-15 04:10:20

Miałem ten sam problem z poniższym kodem.

-(void)adjustImageToImageView:(UIImage*)img{

float numPixels = 100;
float radius = 5;
UIGraphicsBeginImageContext(CGSizeMake(numPixels, numPixels));
CGContextRef c = UIGraphicsGetCurrentContext();

CGContextBeginPath(c);
CGContextMoveToPoint  (c, numPixels, numPixels/2);
CGContextAddArcToPoint(c, numPixels, numPixels, numPixels/2, numPixels,   radius);
CGContextAddArcToPoint(c, 0,         numPixels, 0,           numPixels/2, radius);
CGContextAddArcToPoint(c, 0,         0,         numPixels/2, 0,           radius);
CGContextAddArcToPoint(c, numPixels, 0,         numPixels,   numPixels/2, radius);
CGContextClosePath(c);

CGContextClip(c);

[img drawAtPoint:CGPointZero];
UIImage *converted = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.imageView.image = converted;   }

Wziąłem funkcję z aplikacji open source Twitterfon.

Kiedy próbowałem naprawić problem, próbowałem zmienić ostatnią linię na

self.imageView.image = [converted retain]

I to zatrzymało komunikaty o błędach w konsoli. Niedługo sprawdzę to w przeciekach, żeby zobaczyć, co się dzieje.

 0
Author: infiniteloop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-24 15:08:27

Chciałam jeszcze raz potwierdzić, że otrzymałam:

Wskaźnik uwolniony nie został przydzielony

Błąd i zniknął, jeśli zmienię mój docelowy os NA 3.1 zamiast 3.0

 0
Author: mracoker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-19 02:45:57

Zmagałem się z tym samym błędem w kodzie. To, co mnie zdziwiło, to to, że moja aplikacja działała w OS 3.0 bez żadnego problemu, dopóki nie dokonałem drobnej modyfikacji kodu, który nie ma nic wspólnego z cgimage* rzeczy. Ale kiedy zaczęło zawodzić, to nigdy nie działało bez awarii. Kiedy przełączyłem się na 3.1, wszystko działało ponownie. Zawęziłem błąd do wywołania cgimagerelease (). Albo usunięcie tej linii, albo dodanie zachowku na wynikowym interfejsie rozwiązało problem-chociaż to jest nie rozwiązanie, ponieważ aplikacja będzie wyciek pamięci.

Próbowałem używać NSZombie z instrumentami. To nie pomogło - aplikacja zawiesiła się bez wykrycia Zombie.

Ponadto własne przykładowe aplikacje Apple (takie jak TheElements) nie ulegają awarii, ale używają tego samego kodu co moja aplikacja. Trudno mi się więc pogodzić z problemem tkwiącym w strukturach. Na razie przechodzę na 3.1 i idę dalej.

 0
Author: Ephraim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-06 05:47:53

To może być tylko ja, ale nie możesz tego zrobić ?

UIImage *whiteMasked = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

return whiteMasked;

WhiteMasked jest przydzielany na stosie funkcji i po jej zwróceniu wskaźnik nie jest już ważny? Czy coś przeoczyłem? Jeśli użyjesz zwróconego Interfejsu*, nie ma gwarancji, że nadal tam będzie. (byłoby to hit I miss). Czy nie musisz przydzielać UIImage*, a następnie autorelease go przed powrotem?

 0
Author: dkardell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-01 16:53:27