1

ポイント:ARCを使用。 完全なエラーは:15000回の反復後、「エラー:領域を割り当てることができません」 - メモリ警告なし

malloc: * mmap(size=2097152) failed (error code=12) error: can't allocate region ** set a breakpoint in malloc_error_break to debug

4回です。

質問への任意の物質の唯一のコードは次のとおりです。問題が何であるか

- (void)didReceiveMemoryWarning 
{ 
    NSLog(@"Error near iteration %ld", iteration); 
    [super didReceiveMemoryWarning]; 
} 

任意のアイデア:

-(void)iterate:(NSString *)string{ 
    frontString = NULL; 
    backString = NULL; 
    arrayOfNumbers = NULL; 
    backwardArrayOfNumbers = NULL; 
    nextString = NULL; 
    nextArrayOfNumbers = NULL; 
    nextArrayOfNumbers = [NSMutableArray new]; 
    nextString = [NSMutableString new]; 
    backwardArrayOfNumbers = [NSMutableArray new]; 
    arrayOfNumbers = [NSMutableArray new]; 
    frontString = [[NSMutableString alloc] initWithString:string]; 
    backString = [NSMutableString new]; 
    if (string.length > 1) { 
     iteration++; 
     for (unsigned long i = 0; i < string.length; ++i) { 
      NSString *sub = [string substringWithRange:(NSRange){i, 1}]; 
      [arrayOfNumbers addObject:sub]; 
      NSString *back = [string substringWithRange:(NSRange){string.length-(i+1), 1}]; 
      [backwardArrayOfNumbers addObject:back]; 
      [backString appendString:back]; 
      sub = NULL; 
      back = NULL; 
     } 

     if ([frontString isEqualToString:backString]) { 
      [palindromicNumberTextView setText:string]; 
      [iterationLabel setText:[NSString stringWithFormat:@"%ld", iteration]]; 
     } else { 
      int carrier = 0; 
      for (long long j = arrayOfNumbers.count-1; j > -1; --j) { 
       int a = [[arrayOfNumbers objectAtIndex:j] intValue]; 
       int b = [[backwardArrayOfNumbers objectAtIndex:j] intValue]; 
       //NSLog(@"a = %i, b = %i", a, b); 

       int c = a+b+carrier; 
       if (c > 9) { 
        c = c-10; 
        carrier = 1; 
       } else { 
        carrier = 0; 
       } 

       [nextArrayOfNumbers addObject:[NSString stringWithFormat:@"%i", c]]; 
       if (carrier == 1 && (nextArrayOfNumbers.count == arrayOfNumbers.count)) { 
        [nextArrayOfNumbers addObject:[NSString stringWithFormat:@"%i", carrier]]; 
       } 
       //NSLog(@"nextArrayOfNumbers = %@", nextArrayOfNumbers); 
      } 

      for (int i = 0; i < nextArrayOfNumbers.count; ++i) { 
       NSString *back = [nextArrayOfNumbers objectAtIndex: nextArrayOfNumbers.count-(i+1)]; 
       //NSLog(@"back = %@", back); 
       [nextString appendString:back]; 
       back = NULL; 

      } 
      if (iteration%1000 == 0) { 
       NSLog(@"iteration %ld; count:%u", iteration, nextArrayOfNumbers.count); 
      } 
      //NSLog(@"iteration %ld", iteration); 
      [self iterate:nextString]; 
     } 
    } 
} 

15,000メモリーなしの警告と反復の後に、クラッシュ+エラー、 ?前もって感謝します!

編集:CStringNSStringの間の変換は、ARCの痛みです。だから私はループ内に@autoreleasepool{}(そして、NULLではなくnil)と一緒に行き、それは劇的にメモリ使用量を減らしました。私は50k回以上の反復をしています。

+2

は、私はこの権利を読んでいますか?あなたは真剣に再帰の深さが15,000レベルに達していますか?そして、なぜあなたは記憶がなくなっているのだろうと思いますか? –

+0

いいえ、私は機能的な環境で見たものの3分の1以下のNSMutableArrayを使ってメモリが不足しているのだろうと思います。再帰のプロセス自体が記憶を食べるか? – AMayes

+1

再帰するたびに、これらの配列の新しいコピーを作成します。 –

答えて

1

このように多くのメモリを使用している場合、プログラム自体に問題があります。このメモリのメモリ使用量を大幅に減らすことができます。

とにかく、がメインスレッドで行われた場合は、メモリの警告が表示されません。メモリの警告はメインスレッドで行われ、メインスレッドの実行ループが通常の作業(メモリ警告の処理や他のイベントの処理など)を行う前にメモリを使い切ってしまうため、警告を処理する機会はありません。

おそらく、これがセカンダリスレッドで発生した場合は別のものが表示されますが、それは問題の根本を解決しません。

+0

"このアルゴリズムのメモリ使用量を大幅に削減できます。 - どうですか? – AMayes

+0

繰り返し、再帰しないで、明示的に自動解放プールを作成して破棄し、autoreleaseは何も(あなたの実装で)何も格納していないときには文字列の代わりに数字を使う。あなたが入口でNULLのイナール - あなたはそれらを解放するのですか?レビューとプロフィールを作成し、別のパスを取得します。 Cタイプの少量のスタックスペースを使用して実装の肉体を作ることができます。 c実装は多くの多くの場合、何度も何度も高速に実行されます。オートリリースしないCFタイプを使用しても、問題をよりよく理解するのに役立ちます。 – justin

0

メモリをいっぱいにする問題を再帰的に解決しています。

お使いのコンピュータは、15,000サイクルごとに終了する場所を把握しておく必要があります。それは多くのスペースになる可能性があります。

この「末尾再帰」を可能にすると、スペースを節約できます。例えば:

"bad" recursion which saves in memory 7 + 6 + 5 + 4 + 3 + 2 
int factorial (int x) 
{ 
    if (x > 1) 
    { 
    return (x + recursion (x - 1)); 
    } 
    else return x; 
} 

//

good recursion start with y = 1 
only saves in memory two integers, updating them every cycle. 
int factorial (int x, int y) 
{ 
    if (x > 1) 
    { 
    return factorial (x - 1, (x * y)); 
    } 
    else return x; 
} 
+0

さて、これは私にとってナンセンスです。つまり、私は重要な点を見逃しています。これは私のコードとどのように関係していますか? – AMayes

関連する問題