2011-06-24 6 views
0

私のプログラムの基本的な構造では、ユーザーが格納されたテキストファイルに対応するUITableViewから項目を選択します。ファイルは配列と辞書に読み込まれます。配列にはキーがあります(私は辞書自体からキーを取得できますが、これは私の質問ではありません)。ファイルから読み取るときにクラッシュログなしでiPadアプリがクラッシュする

ビューは、マスタビューにキーがあるUISplitViewに変更され、ディテールビューには、そのキーに関連付けられているディクショナリ内の項目があります。この場合、ユーザーが回答を選択する一連の「はい/いいえ」の質問です。

私の問題はこれです:UITableView(最初の画面)のセルをクリックすると、正常に動作し、データは完全に読み込まれます。私がUITableViewに戻り、同じセルをもう一度クリックすると、プログラムがクラッシュします。ここで、リードイン-からのファイルの方法は次のとおりです。

-(NSArray *)readFromFile:(NSString *)filePath{ 
    // NSLog(@"Path was: %@", filePath); 
    NSString *file = [[NSString alloc] initWithContentsOfFile:filePath]; 

    // NSLog(@"File was: %@", file); 
    NSScanner *fileScanner = [[NSScanner alloc] initWithString:file]; 

    NSString *held; 
    NSString *key; 
    NSMutableArray *detailStrings; 
    NSMutableArray *keys = [[NSMutableArray alloc] init]; 
    NSMutableDictionary *details = [[NSMutableDictionary alloc] init]; 
    /** 
    This is where the fun stuff happens! 
    **/ 
    while(![fileScanner isAtEnd]){ 
     //Scan the string into held 
     [fileScanner scanUpToString:@"\r" intoString:&held]; 
     NSLog(@"Inside the while loop"); 
     // If it is a character, it's one of the Key points, so we do the management necessary 
     if ([[NSCharacterSet lowercaseLetterCharacterSet] characterIsMember:[[held lowercaseString] characterAtIndex: 0]]){ 
      NSArray *checkers = [[NSArray alloc] initWithArray:[held componentsSeparatedByString:@"\t"]]; 
      NSLog(@"Word at index 2: %@", [checkers objectAtIndex:2]); 

      if(detailStrings != nil){ 
       [details setObject:detailStrings forKey:key]; 
       [detailStrings release]; 
      } 
      NSLog(@"After if statement"); 
      key = [checkers objectAtIndex:2]; 
      [keys addObject:(NSString *) key]; 
      detailStrings = [[NSMutableArray alloc] init]; 
     } 
     else if ([[NSCharacterSet decimalDigitCharacterSet] characterIsMember:[[held lowercaseString] characterAtIndex: 0]]){ 

      NSArray *checkers = [[NSArray alloc] initWithArray:[held componentsSeparatedByString:@"\t"]]; 
      NSLog(@"Word at index 1: %@", [checkers objectAtIndex:1]); 
      [detailStrings addObject:[checkers objectAtIndex:1]]; 
     } 
    } 
    NSLog(@"File has been read in"); 
    [details setObject:detailStrings forKey:key]; 
    NSArray *contents = [[NSArray alloc] initWithObjects:(NSMutableArray *) keys, (NSMutableDictionary *) details, nil]; 

    [detailStrings release]; 
    return contents; 
} 

私は

if(detailStrings != nil) 

文の中のプログラムがクラッシュすることを決定しました。これは、私がやっているはずのメモリ管理が行方不明だからだと思うが、どこが間違っているのか分からないからだ。問題についてのアイデア、または私にログを与えずにクラッシュする理由は何ですか?

+0

を読むなぜあなたはチェックしますか?明らかに、if文の前に値を割り当てたことはありません。それとも私は何かが恋しい? –

+0

コールスタックとは何か、またはクラッシュする理由を教えてください。 –

+0

さらに考えてみたら、解放されたポインタ 'detailStrings'があると思います。それを再定義しても、それは「無」にはなりません。 –

答えて

3

detailStringsは、whileループを入力すると初期化されません。メソッド内にNSMutableArray *detailStrings;を宣言すると、detailStringsは自動的にnilに設定されません。ですから、

if (detailStrings != nil) { .. } 

を行うときには、if文を入力し、それが初期化されていないので、あなたがdetailStringsにアクセスすると、それがクラッシュします。

detailStringsは、ループの最初の部分にelseが入ると初期化されません。それもクラッシュを引き起こします。だからあなたの要件に基づいて、いずれかの

NSMutableArray *detailStrings = nil; 

を行うか、whileループに入る前に、それを初期化します。

+0

私は新しく定義されたすべての変数が自動的にnilであることを確信しています。定義の後にブレークポイントを置いて、その変数があれば値を取得することで、自分でテストすることができます。 0x0(nil)と等しくなります。変数が他の場所で使用されていない限り、これはもう必要ないとき(競合条件がコード内で発生する可能性があるとき)に値をゼロにすることは悪い考えではありません。 –

+0

問題は、変数がすでに定義されている場合にのみ発生します。無料のポインタ、誰かが言うかもしれません。解決策は実際には 'nil'を割り当てています。 –

+1

@Randy Marsh:Objective-Cの新しく定義された変数は自動的にはnilではないという事実を知っています。それらがクラスメンバ変数であれば、 'alloc'が割り当てるメモリをクリアするので、' detailStrings 'のようなスタック変数のような他のメモリ割り当ては、スタック上の何かの値を取得するだけです。 – benzado

2

Deepakは真実を言った。まず、detailStringをnilで初期化する必要があります。

しかし、第二の可能な問題があります:

次のループであなたがnilでメモリの存在しない部分をテストすることがあるので、私は、リリース後にnilを設定することもお勧めします。

if(detailStrings != nil){ 
      [details setObject:detailStrings forKey:key]; 
      [detailStrings release]; 
      detailStrings = nil; 
} 

そして、第3の可能な問題:あなたは、IF文は初めての第二部に移動し、非初期化された配列にのaddObjectにしようとして入ってくるデータから垂れ下がります。

第四(最後の希望):この時点で

//read in the file 
NSString *file = [[NSString alloc] initWithContentsOfFile:filePath]; 
//create the scanner 
NSScanner *fileScanner = [[NSScanner alloc] initWithString:file]; 

//declare some uninitialized stuff 
NSString *held; 
NSString *key; 
NSMutableArray *detailStrings; 

//initialize some stuff 
NSMutableArray *keys = [[NSMutableArray alloc] init]; 
NSMutableDictionary *details = [[NSMutableDictionary alloc] init]; 

//begin loop 
while(![fileScanner isAtEnd]){ 
    //scan up to a newline 
    [fileScanner scanUpToString:@"\r" intoString:&held]; 
    //see if you scanned a lowercase string 
    if ([[NSCharacterSet lowercaseLetterCharacterSet] characterIsMember:[[held lowercaseString] characterAtIndex: 0]]){ 
     //make an array 
     NSArray *checkers = [[NSArray alloc] initWithArray:[held componentsSeparatedByString:@"\t"]]; 

     //do a check... against an uninitialized value 
     if(detailStrings != nil){ 
      //set a potentially uninitialized value into an array with an uninitialized key 
      [details setObject:detailStrings forKey:key]; 

が、あなたはかなりまずいしている:あなたは「チェッカー」配列

1

ここで私が見ているものだとメモリリークを持っています。

修正: `detailStrings`は` nil`ある場合

  • 適切
  • あなたの変数を初期化するには、
  • 静的アナライザを実行するには、メモリ管理プログラミングガイドに
+0

ガイドを今読んでください。それを見てくれてありがとう! – Althane

関連する問題