views:

28

answers:

2

I know this is a long-shot, but since I need this code to work, maybe someone here can help.

I'm using the Irregularly Shaped Buttons code from CodeProject.com in one of my iPhone apps. Works great, but Instruments is reporting two memory leaks. I'm using the code in a standard UIViewController, but that is inside a UINavigationController, which might be where the problems lie.

The first leak is reported in the myInit method of clickThruButton.m

- (void) myInit
{
    // Set so that any alpha > 0x00 (transparent) sinks the click
    uint8_t threshold = 0x00;
    self.alphaMask = [[AlphaMask alloc]  initWithThreshold: threshold]; 
    [self setMask];
}

I can see the release down below, so I'm not sure why this would leak:

- (void)dealloc
{
    [self.alphaMask release];
    [super dealloc];
}

Perhaps we first need to check to see if self.alphaMast is nil before doing the alloc?

The second is at the end of the calcHitGridFromCGImage method in AlphaMask.m:

// COPIES buffer
// is AUTORELEASED!
// http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/
// MemoryMgmt/Articles/mmRules.html#//apple_ref/doc/uid/20000994-BAJHFBGH
NSData* ret = [NSData dataWithBytes: (const void *) dest 
                             length: (NSUInteger) destBytes ];

CGContextRelease (alphaContext);
free (alphaGrid);
free (dest);

return ret;

The leak appears on the NSData assignment. There's no alloc, new or copy, so where's the leak?

I would REALLY appreciate any help you could provide here. I know it's a stretch, but I need this to work ASAP. Thanks!

UPDATED:

The full source can be found at the link above, but this may help clear up the alphaMask definition:

//
//  ClickThruButton.h
//  Test
//
//  Pi

@class AlphaMask;

@interface clickThruButton : UIButton 
{
    @private AlphaMask* _alphaMask;
}

@end

and...

//
//  ClickThruButton.m
//  Test
//
//  Pi

#import "clickThruButton.h"
#import "AlphaMask.h"

@interface clickThruButton ()

@property (nonatomic, retain) AlphaMask* alphaMask;

- (void) myInit;
- (void) setMask;

@end

@implementation clickThruButton

@synthesize alphaMask = _alphaMask;
A: 

self.alphaMask = [[AlphaMask alloc] initWithThreshold: threshold]; is likely a leak. Without seeing the definition of that property I can't say for sure though.

Joshua Weinberg
+2  A: 

(1)

The alphaMask property is likely set to -retain. This causes the retain count to increase by 1 automatically when set. But [AlphaMask alloc] already returns an object with retain count of +1, so the overall retain count is excessively +2.

The [self.alphaMask release] later can only decrease the retain count by 1, so finally the count cannot get to 0 and deallocate, i.e. the memory will be leaked.

You should rewrite that as

AlphaMask* mask = [[AlphaMask alloc]  initWithThreshold: threshold];
self.alphaMask = mask;
[mask release];        // cancel the retain.

(2)

I don't think there's any leak in this piece of code.

KennyTM
Brilliant! I *think* that fixed it. Thank you!
Axeva