2012-05-10 8 views
0

私が今持っていますと、メモリリークの問題、メモリ管理は

@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

classA.h

です

+ (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; } 

警告:(「自己」を介して)インスタンス変数のアクセスヌルポインタ参照の結果は

質問:なぜ私はこの警告を取得し、どのようにこの問題を解決することになっています。 アドバイスをお願いします。おかげ

+0

はクラスA *クラスA = [[クラスAのALLOC] initWithData:データ]における第一および第三のクラスAです。それはタイプミスであるため小文字ですか? – fsaint

+0

ありがとう。私はちょうど – tranvutuan

答えて

1

は[rxmlrRoot itertate ...などを移動していること

if (self) { 

} 

にすべての初期化コードを入れてみてください。一般的なルールとして声明

場合にに、すべての初期化構文(initメソッドですべてが!)、もし(自己)ブロックでなければなりません。その理由は、スーパークラスがnilを返したときに実行されるブロックの外側のコードです(else if if(!self){...)。 superメソッド(初期化子がO-Cの通常のメソッドに過ぎない)が呼び出されなかった場合、コードを実行し続ける必要はありません。

私も常にこの指定イニシャライザを呼び出して、私のカスタムクラス(これはスーパーのinitを呼び出すために取得一つです)、私のクラス内の他のすべてのinitialzersに指定イニシャライザを持つように教えられました。 Ex。

// 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つのポイントからのすべてのトラフィックを制御できます。コール[rxmlRoot iterate:node with:^(RXMLElement *e){ ... }]

+0

感謝を編集した、警告が消えているが、私はまた、同様の警告の説明を必要としています。 – tranvutuan

+2

あなたは自己がゼロかもしれないと言っているので、コンパイラは言っています - 自己がnilの場合、 'arr'のような他のnilを使うコードに行くとクラッシュするでしょう。あなたはもちろん、自己が決して無限にならないことを「知っている」(あなたがメモリ上で低ければ、とにかくクラッシュするだろう!) - コンパイラはそれを知らない。 –

+0

@ttran Tomが言ったことは正しかったです。答えに説明を追加しました。同様の問題:http://stackoverflow.com/questions/10246945/instance-variable-access-via-self-results-in-a-null-pointer-dereference – Patrick

0

、ノードは何ですか?ローカル変数でもiVarでもありません。それはグローバルなのでしょうか、それとも他のどこかに存在しますか?それは今までに何

、これは初期化されている確認してください。

0

は、ブロックの内部では、インスタンス変数arrは、参照することによりアクセスされています。微妙なメモリ管理ルールのために、アクセスによってselfがブロックによって保持されます。

selfがnilである可能性があるので、if (self)はコンパイラの手掛かりなので、ブロックによる暗黙的な保持であるselfは、ヌルポインタ逆参照を引き起こす可能性があります。

初期ゼロと出口を確認し、修正する:

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