0

1 秒に 1 回起動する NSTimer があります。

そして毎秒、変更が必要な NSString があります。

私はこれまでメモリ管理を試みたことがないので、私がしていることが正しいかどうかはわかりませんが、楽器は「alloc」の下でstringByReplacingOccurrencesOfString、約1分後にコード行に45MBの「Live Bytes」があると言っています...

(そして、ライブバイト数は毎秒増加し続け、最終的にアプリをクラッシュさせます)。

私の問題はMutableCopyコードのどこかにあると思いますか?

これが私のコードです:

-(void)myTimer {
    if (testedit) {
        [testedit release];
        [withString1a release];
        [forString1a release];
    }
    testedit = [[NSString alloc] init];
    withString1a = [[NSString alloc] init];
    forString1a = [[NSString alloc] init];

    testedit = [[NSString alloc] initWithFormat:@"example"];
    withString1a = [[NSString alloc] initWithFormat:@"e"];//this string gets its values randomly from an array in my real code
    forString1a = [[NSString alloc] initWithFormat:@"flk34j"];//this string gets its values randomly from an array in my real code

    testedit = [[testedit stringByReplacingOccurrencesOfString:withString1a withString:forString1a]  mutableCopy];//memory leak /:

}
4

4 に答える 4

2

各オブジェクトに 2 回メモリを割り当てています。2 回目に割り当てて同じ変数に割り当てると、割り当てられたメモリの最初の部分にアクセスできなくなり、解放できなくなります。

次に、testedit の mutableCopy を作成し、コピーを元の変数に割り当てます。繰り返しますが、アクセスできないメモリの一部が浮かんでいます。

非 ARC メモリ管理のルールは、 allocnewcopy、またはkeepごとに、対応するreleaseが必要です。6 つの割り当て、1 つのコピー、および 3 つのリリースしかありません。

ここにいくつかの提案があります。

これらの重複した割り当てを削除します。

   testedit = [[NSString alloc] init];
   withString1a = [[NSString alloc] init];
   forString1a = [[NSString alloc] init];

おそらくtesteditwithString1aおよびforString1aはすべて iVar です。( iVar を自動合成されたプロパティとして宣言し、それらを self.testedit ... として参照してください。これにより、オーバーフローをスタックするコードが非常に明確になります)。

これをすべて取り出します:

if (testedit) {
        [testedit release];
        [withString1a release];
        [forString1a release];
    }

これらがすべて iVar であると仮定すると、それらを解放する正しい場所はオブジェクトのdeallocメソッドにあります。

実際withString1aforString1aは、コンテンツを他の場所から取得するため、ローカル変数にすることができます。

 NSString*  withString1a = [[[NSString alloc] initWithFormat:@"e"] autorelease];
 NSString*  forString1a =  [[[NSString alloc] initWithFormat:@"flk34j"] autorelease];

autoreleaseメソッドが終了した後にぶらぶらする必要がないので、それらを使用できます。

これらの行は次のようにも記述できます。

 NSString*  withString1a = [NSString stringWithFormat:@"e"];
 NSString*  forString1a =  [NSString stringWithFormat:@"flk34j"];

(-stringWithFormat は、自動解放されたオブジェクトを返す便利なメソッドです)

残りはこの 2 行です。

  testedit = [[NSString alloc] initWithFormat:@"example"];
  testedit = [[testedit stringByReplacingOccurrencesOfString:withString1a 
                                                  withString:forString1a]  mutableCopy];

testit を最初の行で不変の文字列として、2 番目の行で変更可能な文字列として扱う理由は明らかではありません。testedit新しい文字列に置き換えているため、ここでは変更可能な文字列はまったく必要ありません。

 self.testedit = [[NSString alloc] initWithFormat:@"example"];
 self.testedit = [[testedit stringByReplacingOccurrencesOfString:withString1a 
                                                  withString:forString1a] copy]; 

copy(自動解放されたオブジェクトを返す必要がありstringByReplacingOccurrencesOfString:withString:、ここではそれを保持したい)

ジグソーパズルの最後のピースは、_testedit iVar メモリ割り当てを取り除くことです。オブジェクトのメソッドでこれを行いdeallocます。

- (void) dealloc {
    [_testEdit release];
    [super dealloc];
}

( init、アクセサ、およびメソッドは、プロパティ構文を使用して iVar を参照してはならないdealloc3 つの場所であることに注意してください。)

大丈夫ですが、実際には ARC を使用する必要があります。この方法では、メモリの管理をコンパイラに依存する場合よりも、メモリのバグが発生する可能性がはるかに高くなります。

于 2013-01-22T22:37:07.693 に答える
1

ここを利用することをお勧めします@property

.h ファイルで、プロパティを次のように宣言します。

@property (nonatomic, retain) NSString *testedit;
@property (nonatomic, retain) NSString *withString1a;
@property (nonatomic, retain) NSString *forString1a; //if required write the @synthesize as well in .m class

タイマー メソッドは次のように記述できます。

-(void)myTimer {

    self.testedit = @"example";
    self.withString1a = @"e";//this string gets its values randomly from an array in my real code
    self.forString1a = @"flk34j";//this string gets its values randomly from an array in my real code
    self.testedit = [self.testedit stringByReplacingOccurrencesOfString:self.withString1a withString:self.forString1a];
}

dealloc メソッドでは、上記のすべてのプロパティをnil( self.testedit = nil;) として設定するか、それらを解放する ( [testedit release];) ことができます。

可能であれば、ARC に切り替えてみてください。メモリ管理について心配する必要はありません。コードの問題は、実行する前に変数を解放せずに多くの alloc/init ステートメントを使用していることです。これにより、その変数の参照が失われ、リークします。それほど多くの割り当てステートメントは必要ありません。すべての割り当てまたは保持に対して、対応する解放/自動解放ステートメントが必要です。

于 2013-01-22T23:01:51.890 に答える
0

If you're using ARC you shouldn't have an issue. If you aren't using ARC you can try adding autorelease:

testedit = [[[testedit stringByReplacingOccurrencesOfString:withString1a withString:forString1a]  mutableCopy] autorelease];
于 2013-01-22T22:44:35.233 に答える
0

割り当てを解除しないため、メモリリークが発生していますtestedit。alloc を呼び出すときはいつでも、それを解放する必要があることを意味します。これは通常、 を呼び出すことを意味しreleaseます。

代わりに次のようにして、割り当てたメモリを解放してください。

NSString* newString = [[testedit stringByReplacingOccurrencesOfString:withString1a withString:forString1a]  mutableCopy];
于 2013-01-22T22:38:00.037 に答える