泄漏内存问题,内存管理

时间:2012-05-10 18:33:41

标签: iphone objective-c memory-management

我现在拥有的是

classA.h

@interface ClassA: NSObject <DelegateA>
-(id)initWithData:(NSData*)data;
+(Stores*)makeClass:(Class) name fromData:(NSData*)data;
@property (assign) NSMutableArray    *arr;
@property (assign) RXMLElement       *rxmlRoot;
@end

classA.m

   -(id)initWithData:(NSData*)data { 
        self = [super init]; 
        if (self) { 
            arr      = [[NSMutableArray array] retain]; 
            rxmlRoot = [[RXMLElement elementFromXMLData:data] retain]; 

        } 

        [rxmlRoot iterate:node with:^(RXMLElement *e){   <--------get warning at here
            NSLog(@"element is %@",e.tag);
            Detail   *detail  =   [[[Detail alloc] init] autorelease];
            [detail setLat:       [e attribute:@"lat"]];
            [detail setLon:       [e attribute:@"lon"]];

            [arr addObject:detail];

        }];
        return self; 
        }

      +(classA*)makeClass:(Class) name fromData:(NSData*)data{
            ClassA  *classA =   [[ClassA alloc] initWithData:data];
            return [storeClass autorelease] ;

        }

和RaptureXML.m

+ (id)elementFromXMLData:(NSData *)data {
    return [[[RXMLElement alloc] initFromXMLData:data] autorelease];
}
- (id)initFromXMLData:(NSData *)data {
    if ((self = [super init])) {
        xml_ = [[TBXML alloc] initWithXMLData:data];
        tbxmlElement_ = xml_.rootXMLElement;
    }

    return self;    
}

警告:实例变量访问(通过'self')导致空指针取消引用

问题:为什么我收到此警告以及如何解决此问题。 请就此向我提出建议。感谢

3 个答案:

答案 0 :(得分:1)

尝试将所有初始化代码放在

if (self) {

}

即移动[rxmlrRoot itertate ...等。进入那个if语句

作为一般规则,所有初始化语法(init方法中的所有内容!)都应该在if(self)块中。原因是当超类返回nil时,该块外部的代码将运行(想想如果(!self){...)。如果没有调用super方法(初始化程序只是O-C中的常规方法),则不希望代码继续执行。

我还被教导在我的自定义类中总是有一个指定的初始化器(这是调用super init的那个),我班级中的所有其他初始化器然后调用这个指定的初始化器。实施例

// Designated initializer
- (id)init
{
    self = [super init];
    if (self) {
        // initialize some stuff
    }

    // else { something went wrong and super returned nil..
    // don't put anything here

    return self;
}

// Another initializer
- (id)initWithFoo:(int)foo
{
    self = [self init]; // Now i call my designated initializer instead of super
    if (self) {
        self.foo = foo; // or something
    }
}

这使您可以控制该点的所有流量。

答案 1 :(得分:0)

在电话[rxmlRoot iterate:node with:^(RXMLElement *e){ ... }]中,什么是节点?它不是局部变量,也不是iVar。它是全球性的还是存在于其他地方?

无论如何,请检查以确保已初始化。

答案 2 :(得分:0)

在块内部,通过引用访问实例变量arr。由于存在细微的内存管理规则,访问会导致self被块保留。

由于if (self)是编译器的线索self可能为nil,因此块隐式保留self可能会导致空指针解除引用。

要修复,请检查nil并提前退出:

if (!(self = [super init])) {
    return nil;
}

// now it is impossible for self to be nil and cause a null pointer dereference
// when self is implicitly retained by the block

// ...continue initialization