使用 Instruments 面板的 iPhone 新手开发人员:我的泄漏在哪里?

发布于 2024-09-19 00:22:49 字数 9838 浏览 4 评论 0原文

更新


我已经更新了planets.m/h文件以反映评论者提出的建议(谢谢bbum和DarkDust。 我的工厂方法现在都调用 autorelease 并且看起来像这样:

- (Planet *) initWithName: (NSString *)name;
+ (Planet *) planetWithNameAndMoons:(NSString *)name moons:(id)firstObj, ... NS_REQUIRES_NIL_TERMINATION;
+ (Planet *) planetWithName:(NSString *)name;
+ (Planet *) planetWithResultSet:(FMResultSet *)resultSet;

现在我的 init 现在看起来像这样

- (id)init {
    self = [super init];
    self.Id = 0;
    self.SupportsLife = NO;
    self.Moons =  [NSMutableArray array];   
    return self;
}

我在我的第二个控制器中从根调用planetWithName。这就是我使用它的方式

- (Planet *)newPlanet
{
    int i = 0;
    Planet *planet = nil;
    NSMutableDictionary *criteria = [NSMutableDictionary new];

    do {
        i += 1;
        [criteria setValue: [NSString stringWithFormat:@"Planet %d", i] forKey: @"Name"];
        planet = [[PlanetRepo SharedRepo] Find: criteria];
    } while (planet != nil);    // if a planet is found with that name, keep looking...

    planet = [Planet planetWithName: (NSString *)[criteria valueForKey:@"Name"]];
    [planet retain];

    [criteria release];
    criteria = nil;

    return planet;
}

这是我的 PlanetRepo 类(注意,它环绕 FMDB) PlanetRepo.h

#import <Foundation/Foundation.h>
#import "Planet.h"

@interface PlanetRepo : NSObject { 
    FMDatabase * _repoSource;
}

+ (PlanetRepo *) SharedRepo;

- (Planet *)Find:(NSDictionary *)criteria;
- (NSMutableArray *)GetAll;
- (Planet *)GetById:(id ) Id;
- (BOOL) Save:(Planet *) planet;
- (BOOL) Delete: (Planet *) planet;

- (BOOL) Open:(NSString *)repoSource;
- (void) Close;

@end

@interface PlanetRepo (Private)
- (NSError *) CreateDatabaseIfNeeded:(NSString *)databasePath;
@end

Planet.m

#import "FMDatabase.h"
#import "PlanetRepo.h"
#import "Planet.h"

@implementation PlanetRepo

+ (PlanetRepo *)SharedRepo 
{   
    static PlanetRepo *_sharedRepo;
    @synchronized(self) 
    {
        if (!_sharedRepo) 
            _sharedRepo = [[super alloc] init]; 
    }
    return _sharedRepo;
}

+ (id) alloc { 
    return [self SharedRepo]; 
}

- (BOOL) Open: (NSString *)repoSource 
{   
    NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *databasePath = [documentsDirectory stringByAppendingPathComponent: repoSource];
    NSError *error = [self CreateDatabaseIfNeeded: databasePath];

    BOOL result = (error == nil);
    if(result) 
    {
        _repoSource = (FMDatabase *)[FMDatabase databaseWithPath:databasePath];
        [_repoSource retain];
        result = [_repoSource open];
        if (result) 
            NSLog(@"Planet Repo open successful!");
        else 
        {
            NSLog(@"Could not open Planet Repo.");
            [self Close];
        }
    }       
    else 
        NSLog(@"Could not copy db.", [error localizedDescription]);
    return result;
}

- (void) Close 
{
    [_repoSource release];
    _repoSource = nil;
}

- (void) dealloc 
{
    [self Close];
    [super dealloc];
}

- (Planet *)Find:(NSDictionary *)criteria
{
    if (criteria == nil) return nil;

    const NSUInteger criteriaCount = [criteria count];
    if (criteriaCount == 0) return nil;

    NSMutableString *temp = [NSMutableString stringWithString: @"SELECT Id, Name, SupportsLife FROM planet WHERE"];
    NSMutableArray *values = [[NSMutableArray alloc] initWithCapacity:criteriaCount];
    int i = 0;
    for (id key in criteria) 
    {
        [values addObject: [criteria objectForKey:key]];
        NSLog(@"key: %@, value: %@", key, [values objectAtIndex:i] );

        [temp appendString: [NSString stringWithFormat:@" %@=?", key ] ];
        if ( i < (criteriaCount - 1) ) 
            [temp appendString: @","];
        i++;
    }

    NSString *sql = [NSString stringWithString:temp];
    NSLog(@"sql: [%@]", sql);
    FMResultSet *resultSet = [_repoSource executeQuery:sql withArgumentsInArray: values ];

    Planet *planet = nil;
    if ( [resultSet hasAnotherRow] )
        planet = [Planet planetWithResultSet: resultSet];

    [values release];
    [resultSet close];

    return planet;
}

-(NSMutableArray *)GetAll
{
    NSMutableArray* resultsArray = [[NSMutableArray new] autorelease];
    FMResultSet *resultSet = [_repoSource executeQuery:@"SELECT Id, Name, SupportsLife FROM planet ORDER BY Name ASC"];
    while ([resultSet next]) 
        [resultsArray addObject:  [Planet planetWithResultSet:resultSet] ];
    [resultSet close];

    return resultsArray;
}

- (Planet *) GetById:(id) Id
{
    if( ![_repoSource open]) return NULL;

    Planet *planet = NULL;
    FMResultSet *resultSet = [_repoSource executeQuery:@"SELECT Id, Name, SupportsLife FROM planet WHERE Id=?" withArgumentsInArray:Id];
    if ([resultSet next])
        planet = [Planet planetWithResultSet:resultSet];
    [resultSet close];

    return planet;
}

- (BOOL) Save:(Planet *) planet
{
    if( ![_repoSource open]) return NO;

    [_repoSource beginTransaction];
    BOOL result = NO;
    if (planet.Id == 0) 
    {
        result = [_repoSource executeUpdate: @"INSERT INTO \"planet\" (Name,SupportsLife) values (?,?);", planet.Name, planet.SupportsLife];
        planet.Id = [_repoSource lastInsertRowId];
    }
    else 
        result = [_repoSource executeUpdate: @"UPDATE \"planet\" SET Name=?, SupportsLife=? WHERE Id=?", 
                  planet.Name, 
                  [NSNumber numberWithBool:planet.SupportsLife], 
                  [NSNumber numberWithInt:planet.Id]];


    if (result == YES)
        [_repoSource commit];
    else {
        [_repoSource rollback];
        NSLog( @"%@", [_repoSource lastErrorMessage] );
    }
    return result;  
}

- (BOOL) Delete: (Planet *) planet
{
    if( ![_repoSource open]) return NO;

    [_repoSource beginTransaction];
    BOOL result = [_repoSource executeUpdate: @"DELETE FROM \"planet\" WHERE Id=?", [NSNumber numberWithInt:planet.Id]];

    if (result == YES)
        [_repoSource commit];
    else {
        [_repoSource rollback];
        NSLog( @"%@", [_repoSource lastErrorMessage] );
    }
    return result;  
}

- (NSError *) CreateDatabaseIfNeeded:(NSString *)databasePath 
{   
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL doesDBExist = [fileManager fileExistsAtPath: databasePath];

    if (doesDBExist == NO )
    {
        NSString* dbFileName = [databasePath lastPathComponent];

        //the database does not exist, so we will copy it to the users document directory...
        NSString *sourceDbPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:dbFileName];

        NSError *error;
        if (![fileManager copyItemAtPath:sourceDbPath toPath:databasePath error:&error]) 
        {
            NSLog(@"Could not copy db.", [error localizedDescription]);
            return [error autorelease];
        }
    }
    return nil;
}

@end

原始


我最近一直在努力寻找目标。它是一种很好的语言,但作为一个 .Net 人员,这种内存管理的东西简直要了我的命! :)

我有一个示例类,名为 Planet,当我运行仪表板时,我得到以下内容:

https ://i.sstatic.net/QYdxB.jpg (图片)

Leaked Object |  Address  |   Size   | Responsible Library | Responsible Frame
--------------+-----------+----------+---------------------+-------------------
   Planet     | 0x7136380 | 32 Bytes | NavTest             | +[Planet newWithName:]
   Planet     | 0x712da20 | 32 Bytes | NavTest             | -[Planet init]
   Planet     | 0x5917a20 | 32 Bytes | Foundation          | -[NSPlaceholderString

我认为这意味着我在 [Planet init] 中创建数组时遇到问题?

我也在这里列出了我的类文件。我非常感谢对此的任何帮助。

行星.h

#import <Foundation/Foundation.h>
#import "FMDatabase.h"

@class Planet;

@interface Planet : NSObject { }

@property (nonatomic, assign) int Id;
@property (nonatomic, copy) NSString *Name;
@property (nonatomic, retain) NSMutableArray *Moons;
@property (nonatomic, assign) BOOL SupportsLife;

- (Planet *)initWithName: (NSString *)name;

+ (Planet *) newWithNameAndMoons:(NSString *)name moons:(id)firstObj, ... NS_REQUIRES_NIL_TERMINATION;
+ (Planet *) newWithName:(NSString *)name;
+ (Planet *) readPlanetFrom:(FMResultSet *)resultSet;

@end

行星.m

#import "Planet.h"
#import "FMDatabase.h"

@implementation Planet

@synthesize Id;
@synthesize Name; 
@synthesize Moons; 
@synthesize SupportsLife; 

- (NSString *) description {
 return [NSString stringWithFormat:@"ID: %d\nName: %@", Id ,Name];
}

- (void) dealloc {
 [Moons release];
 [Name release];

 Moons = nil;
 Name = nil;
 [super dealloc];
}

- (id)initWithName:(NSString *)aName {
 self = [self init];
 if (self) self.Name = aName;
 return self;
}

- (id)init {
 self = [super init];
 self.Id = 0;
 self.SupportsLife = NO;
 NSMutableArray *tmp = [NSMutableArray new]; 
 self.Moons = tmp;
 [tmp release];
 tmp = nil;
 return self;
}

+ (Planet *) newWithName:(NSString *)name {
 return [[self alloc] initWithName: name];
}

+ (Planet *)newWithNameAndMoons:(NSString *)name moons:(id)firstObj, ...   {
 Planet *planet = [self newWithName: name];

 va_list args;
    va_start(args, firstObj);
    for (id arg = firstObj; arg != nil; arg = va_arg(args, id))
 {
        [planet.Moons addObject: arg];
  [arg release];
 }
    va_end(args);
 return planet;
}

+ (Planet *) readPlanetFrom:(FMResultSet *)resultSet
{
 Planet *planet = [[self alloc] init]; 
 planet.Id = [resultSet intForColumn:@"Id"];
 planet.Name = [resultSet stringForColumn:@"Name"];
 planet.SupportsLife = [resultSet boolForColumn: @"SupportsLife"];
 return [planet autorelease];
}
@end

Update


I have update the planets.m/h files to reflect the suggestions made by the commentors (thank you bbum and DarkDust.
my factory methods now all call autorelease and look like this:

- (Planet *) initWithName: (NSString *)name;
+ (Planet *) planetWithNameAndMoons:(NSString *)name moons:(id)firstObj, ... NS_REQUIRES_NIL_TERMINATION;
+ (Planet *) planetWithName:(NSString *)name;
+ (Planet *) planetWithResultSet:(FMResultSet *)resultSet;

and now my init now looks like this

- (id)init {
    self = [super init];
    self.Id = 0;
    self.SupportsLife = NO;
    self.Moons =  [NSMutableArray array];   
    return self;
}

I am calling planetWithName in my 2nd controller off the root. This is how I am using it

- (Planet *)newPlanet
{
    int i = 0;
    Planet *planet = nil;
    NSMutableDictionary *criteria = [NSMutableDictionary new];

    do {
        i += 1;
        [criteria setValue: [NSString stringWithFormat:@"Planet %d", i] forKey: @"Name"];
        planet = [[PlanetRepo SharedRepo] Find: criteria];
    } while (planet != nil);    // if a planet is found with that name, keep looking...

    planet = [Planet planetWithName: (NSString *)[criteria valueForKey:@"Name"]];
    [planet retain];

    [criteria release];
    criteria = nil;

    return planet;
}

And here is my PlanetRepo class (note, it is wrapping around FMDB)
PlanetRepo.h

#import <Foundation/Foundation.h>
#import "Planet.h"

@interface PlanetRepo : NSObject { 
    FMDatabase * _repoSource;
}

+ (PlanetRepo *) SharedRepo;

- (Planet *)Find:(NSDictionary *)criteria;
- (NSMutableArray *)GetAll;
- (Planet *)GetById:(id ) Id;
- (BOOL) Save:(Planet *) planet;
- (BOOL) Delete: (Planet *) planet;

- (BOOL) Open:(NSString *)repoSource;
- (void) Close;

@end

@interface PlanetRepo (Private)
- (NSError *) CreateDatabaseIfNeeded:(NSString *)databasePath;
@end

Planet.m

#import "FMDatabase.h"
#import "PlanetRepo.h"
#import "Planet.h"

@implementation PlanetRepo

+ (PlanetRepo *)SharedRepo 
{   
    static PlanetRepo *_sharedRepo;
    @synchronized(self) 
    {
        if (!_sharedRepo) 
            _sharedRepo = [[super alloc] init]; 
    }
    return _sharedRepo;
}

+ (id) alloc { 
    return [self SharedRepo]; 
}

- (BOOL) Open: (NSString *)repoSource 
{   
    NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *databasePath = [documentsDirectory stringByAppendingPathComponent: repoSource];
    NSError *error = [self CreateDatabaseIfNeeded: databasePath];

    BOOL result = (error == nil);
    if(result) 
    {
        _repoSource = (FMDatabase *)[FMDatabase databaseWithPath:databasePath];
        [_repoSource retain];
        result = [_repoSource open];
        if (result) 
            NSLog(@"Planet Repo open successful!");
        else 
        {
            NSLog(@"Could not open Planet Repo.");
            [self Close];
        }
    }       
    else 
        NSLog(@"Could not copy db.", [error localizedDescription]);
    return result;
}

- (void) Close 
{
    [_repoSource release];
    _repoSource = nil;
}

- (void) dealloc 
{
    [self Close];
    [super dealloc];
}

- (Planet *)Find:(NSDictionary *)criteria
{
    if (criteria == nil) return nil;

    const NSUInteger criteriaCount = [criteria count];
    if (criteriaCount == 0) return nil;

    NSMutableString *temp = [NSMutableString stringWithString: @"SELECT Id, Name, SupportsLife FROM planet WHERE"];
    NSMutableArray *values = [[NSMutableArray alloc] initWithCapacity:criteriaCount];
    int i = 0;
    for (id key in criteria) 
    {
        [values addObject: [criteria objectForKey:key]];
        NSLog(@"key: %@, value: %@", key, [values objectAtIndex:i] );

        [temp appendString: [NSString stringWithFormat:@" %@=?", key ] ];
        if ( i < (criteriaCount - 1) ) 
            [temp appendString: @","];
        i++;
    }

    NSString *sql = [NSString stringWithString:temp];
    NSLog(@"sql: [%@]", sql);
    FMResultSet *resultSet = [_repoSource executeQuery:sql withArgumentsInArray: values ];

    Planet *planet = nil;
    if ( [resultSet hasAnotherRow] )
        planet = [Planet planetWithResultSet: resultSet];

    [values release];
    [resultSet close];

    return planet;
}

-(NSMutableArray *)GetAll
{
    NSMutableArray* resultsArray = [[NSMutableArray new] autorelease];
    FMResultSet *resultSet = [_repoSource executeQuery:@"SELECT Id, Name, SupportsLife FROM planet ORDER BY Name ASC"];
    while ([resultSet next]) 
        [resultsArray addObject:  [Planet planetWithResultSet:resultSet] ];
    [resultSet close];

    return resultsArray;
}

- (Planet *) GetById:(id) Id
{
    if( ![_repoSource open]) return NULL;

    Planet *planet = NULL;
    FMResultSet *resultSet = [_repoSource executeQuery:@"SELECT Id, Name, SupportsLife FROM planet WHERE Id=?" withArgumentsInArray:Id];
    if ([resultSet next])
        planet = [Planet planetWithResultSet:resultSet];
    [resultSet close];

    return planet;
}

- (BOOL) Save:(Planet *) planet
{
    if( ![_repoSource open]) return NO;

    [_repoSource beginTransaction];
    BOOL result = NO;
    if (planet.Id == 0) 
    {
        result = [_repoSource executeUpdate: @"INSERT INTO \"planet\" (Name,SupportsLife) values (?,?);", planet.Name, planet.SupportsLife];
        planet.Id = [_repoSource lastInsertRowId];
    }
    else 
        result = [_repoSource executeUpdate: @"UPDATE \"planet\" SET Name=?, SupportsLife=? WHERE Id=?", 
                  planet.Name, 
                  [NSNumber numberWithBool:planet.SupportsLife], 
                  [NSNumber numberWithInt:planet.Id]];


    if (result == YES)
        [_repoSource commit];
    else {
        [_repoSource rollback];
        NSLog( @"%@", [_repoSource lastErrorMessage] );
    }
    return result;  
}

- (BOOL) Delete: (Planet *) planet
{
    if( ![_repoSource open]) return NO;

    [_repoSource beginTransaction];
    BOOL result = [_repoSource executeUpdate: @"DELETE FROM \"planet\" WHERE Id=?", [NSNumber numberWithInt:planet.Id]];

    if (result == YES)
        [_repoSource commit];
    else {
        [_repoSource rollback];
        NSLog( @"%@", [_repoSource lastErrorMessage] );
    }
    return result;  
}

- (NSError *) CreateDatabaseIfNeeded:(NSString *)databasePath 
{   
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL doesDBExist = [fileManager fileExistsAtPath: databasePath];

    if (doesDBExist == NO )
    {
        NSString* dbFileName = [databasePath lastPathComponent];

        //the database does not exist, so we will copy it to the users document directory...
        NSString *sourceDbPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:dbFileName];

        NSError *error;
        if (![fileManager copyItemAtPath:sourceDbPath toPath:databasePath error:&error]) 
        {
            NSLog(@"Could not copy db.", [error localizedDescription]);
            return [error autorelease];
        }
    }
    return nil;
}

@end

Original


I have been working on picking up objective c lately. Its a nice language but as a .Net guy this memory management stuff is killing me! :)

I have a sample class, called Planet, and when I run through instrument panel I get the following:

https://i.sstatic.net/QYdxB.jpg (image)

Leaked Object |  Address  |   Size   | Responsible Library | Responsible Frame
--------------+-----------+----------+---------------------+-------------------
   Planet     | 0x7136380 | 32 Bytes | NavTest             | +[Planet newWithName:]
   Planet     | 0x712da20 | 32 Bytes | NavTest             | -[Planet init]
   Planet     | 0x5917a20 | 32 Bytes | Foundation          | -[NSPlaceholderString

I think this means I have a problem when I am creating an array in the [Planet init]?

I am listing my class file here as well. I would very much appreciate any help on this.

Planet.h

#import <Foundation/Foundation.h>
#import "FMDatabase.h"

@class Planet;

@interface Planet : NSObject { }

@property (nonatomic, assign) int Id;
@property (nonatomic, copy) NSString *Name;
@property (nonatomic, retain) NSMutableArray *Moons;
@property (nonatomic, assign) BOOL SupportsLife;

- (Planet *)initWithName: (NSString *)name;

+ (Planet *) newWithNameAndMoons:(NSString *)name moons:(id)firstObj, ... NS_REQUIRES_NIL_TERMINATION;
+ (Planet *) newWithName:(NSString *)name;
+ (Planet *) readPlanetFrom:(FMResultSet *)resultSet;

@end

Planet.m

#import "Planet.h"
#import "FMDatabase.h"

@implementation Planet

@synthesize Id;
@synthesize Name; 
@synthesize Moons; 
@synthesize SupportsLife; 

- (NSString *) description {
 return [NSString stringWithFormat:@"ID: %d\nName: %@", Id ,Name];
}

- (void) dealloc {
 [Moons release];
 [Name release];

 Moons = nil;
 Name = nil;
 [super dealloc];
}

- (id)initWithName:(NSString *)aName {
 self = [self init];
 if (self) self.Name = aName;
 return self;
}

- (id)init {
 self = [super init];
 self.Id = 0;
 self.SupportsLife = NO;
 NSMutableArray *tmp = [NSMutableArray new]; 
 self.Moons = tmp;
 [tmp release];
 tmp = nil;
 return self;
}

+ (Planet *) newWithName:(NSString *)name {
 return [[self alloc] initWithName: name];
}

+ (Planet *)newWithNameAndMoons:(NSString *)name moons:(id)firstObj, ...   {
 Planet *planet = [self newWithName: name];

 va_list args;
    va_start(args, firstObj);
    for (id arg = firstObj; arg != nil; arg = va_arg(args, id))
 {
        [planet.Moons addObject: arg];
  [arg release];
 }
    va_end(args);
 return planet;
}

+ (Planet *) readPlanetFrom:(FMResultSet *)resultSet
{
 Planet *planet = [[self alloc] init]; 
 planet.Id = [resultSet intForColumn:@"Id"];
 planet.Name = [resultSet stringForColumn:@"Name"];
 planet.SupportsLife = [resultSet boolForColumn: @"SupportsLife"];
 return [planet autorelease];
}
@end

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

二货你真萌 2024-09-26 00:22:49

尽我所能,我无法发现这里的问题。我只有一个非常疯狂的猜测:你是否有一个单独的线程来分配行星?例如通过performSelectorInBackground:?如果是这样,您首先需要设置一个 NSAutoreleasePool 并在方法结束时将其耗尽。如果这确实是问题所在,您会看到类似 *** _NSAutoreleaseNoPool(): Object 0x1234560 of class Foo autoreleased with no pool in place - just Leaking 的消息

不过,我有一条评论:您使用 < code>new 非常不常见。 new[[SomeClass alloc] init] 的同义词。然而,它的使用在 Objective-C 中非常不常见,几乎已被弃用。 。

因此,

tmp = [NSMutableArray new];
self.Moons = tmp;
[tmp release];

更常见的写法是:

self.Moons = [[[NSMutableArray alloc] init] autorelease];

或更好:

self.Moons = [NSMutableArray array];

Try as I might, I can't spot a problem here. I only have a very wild guess: do you have a separate thread where the planet is allocated ? E. g. through performSelectorInBackground: ? If so, you first need to set up a NSAutoreleasePool and drain it at the end of the method. If that really is the problem you would see messages like *** _NSAutoreleaseNoPool(): Object 0x1234560 of class Foo autoreleased with no pool in place - just leaking

Still, I have a comment: Your use of new is quite uncommon. new is a synonym for [[SomeClass alloc] init]. However, its use is very uncommon in Objective-C, almost deprecated.

So instead of

tmp = [NSMutableArray new];
self.Moons = tmp;
[tmp release];

It's more common to write:

self.Moons = [[[NSMutableArray alloc] init] autorelease];

or better yet:

self.Moons = [NSMutableArray array];
陌伤浅笑 2024-09-26 00:22:49

一些问题:

  • 实例变量和属性应该以小写字母开头(为了与类名消除歧义)

  • 没有需要 - 但没有坏处 - 在您的 init 方法中分配 tmp = nil; (需要 if(self) {...} test,顺便说一句)。

  • 您可以通过说 self.moons = [NSMutableArray array]; 来避免使用 tmp 变量;

这可能是泄漏的来源是以下方法:

+ (Planet *) newWithName:(NSString *)name {
 return [[self alloc] initWithName: name];
}

那确实应该是这样的:

+ (id) planetWithName: (NSString *) aName {
    return [[[self alloc] initWithName: name] autorelease];
}

另外,这:

+ (Planet *) readPlanetFrom:(FMResultSet *)resultSet

应该可能是这样的:

+ (id) planetWithResultSet: (FMResultSet *) aResultSet

在没有看到更多代码的情况下,很难确切地说泄漏来自哪里。在打开保留/释放跟踪的情况下,在分配工具下运行代码。选择一个泄漏的行星并查看所有保留/释放事件。会有额外保留。

Some issues:

  • instance variables and properties should start with lower case letters (to disambiguate from class names)

  • there is no need -- but no harm -- in assigning tmp = nil; in your init method (which needs the if(self) {...} test, btw).

  • you could avoid the use of a tmp variable by saying self.moons = [NSMutableArray array];

This is a likely source of leaks is the following method:

+ (Planet *) newWithName:(NSString *)name {
 return [[self alloc] initWithName: name];
}

That really should be something like:

+ (id) planetWithName: (NSString *) aName {
    return [[[self alloc] initWithName: name] autorelease];
}

Also, this:

+ (Planet *) readPlanetFrom:(FMResultSet *)resultSet

Should probably be this:

+ (id) planetWithResultSet: (FMResultSet *) aResultSet

Without seeing more code, it is hard to say exactly where the leak is coming from. Run the code under the Allocations instrument with retain/release tracking turned on. Pick one of the leaking Planets and look at all the retain/release events. There will be an extra retain.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文