4

便宜上、いくつかの作業コードを使用して前の投稿を編集しました。

次のコード(ARC化)がリークしているようで、短時間実行するとシムまたはデバイスがクラッシュします。

#define kROWS 100
#define kCols 34

void run();

static ViewController *instance;

@interface ViewController ()
@property (nonatomic, strong) NSMutableArray *nsBackColor;
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.nsBackColor = [NSMutableArray arrayWithCapacity:1];
    instance = self;

    // set up a '2D array'
    for (int x = 0; x < kROWS; x++) {
        [self.nsBackColor addObject:[NSMutableArray arrayWithCapacity:1]];
        for (int y = 0; y < kCols; y++) {
            [[self.nsBackColor objectAtIndex:x] addObject:[UIColor whiteColor]];
        }
    }

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        run();
    });
}

- (void)plotColor:(UIColor *)color atX:(short)x andY:(short)y {
    [[self.nsBackColor objectAtIndex:x] replaceObjectAtIndex:y withObject:color];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

void plot(short xLoc, short yLoc,
              short backRed, short backGreen, short backBlue) {

    @autoreleasepool {
        [instance plotColor:[UIColor colorWithRed:((float)backRed/100)
                                            green:((float)backGreen/100)
                                             blue:((float)backBlue/100)
                                            alpha:(float)1]
                        atX:xLoc andY:yLoc];
    }
}

void run() {
    short x = 0;
    short y = 0;
    short backRed = 0;
    short backGreen = 0;
    short backBlue = 0;

    while (true) {
        x++;
        if (x >= kROWS) {
            x = 0;
        }

        y++;
        if (y >= kCols) {
            y = 0;
        }

        backRed = arc4random() % 255;
        backBlue = arc4random() % 255;
        backGreen = arc4random() % 255;

        plot(x, y, backRed, backGreen, backBlue);

        usleep(1000);
    }
}

これをデバイスまたはシミュレーターで十分な時間(数分)実行すると、mmap mallocエラー(sim)またはメモリ警告(デバイス)のいずれかが表示され、クラッシュします。

機器の割り当てを確認すると、+ [UIColor colorWithRed:green:blue:alpha:]が、最終的にメモリの壁にぶつかるまでバロンを開始することがわかります。

UIColorをプロパティに(直接またはコピーを実行して)割り当てることができます。たとえば、self.myColor = colorと言うと、そのようなリークはありません。

私もこれを行うことができます:

[[self.nsBackColor objectAtIndex:x] replaceObjectAtIndex:y withObject:[self description]];

そして私は同じリークを取得します。

配列内で置き換えられたオブジェクト(はい、これは元々2D c配列として開始されましたが、それが問題だと思いました)は永久に失われ、リークされ、適切に解放されないようです。

これは、短時間実行した後の[機器]->[割り当て]になります。

楽器

どんな助けでも大歓迎です、そして、より多くの情報が提供されることができます。

4

1 に答える 1

0

何が起こっているのかというと、反復ごとに自動解放プールを作成しているということです。したがって、次の行は、新しい自動解放プールで毎回実行されます。

[[self.nsBackColor objectAtIndex:x] replaceObjectAtIndex:y withObject:color];

したがってcolor、ローカルプール内の参照数を1つ増やし、ローカルプール内の参照数を1つ[[self.nsBackColor objectAtIndex:x] objectAtIndex:y]減らします。ただし、ここに問題があります。そのアイテムはcolor前のイテレーションにあり、その参照カウントは、以前に排出/解放した前のプールによって管理されていました。

したがって、前の反復で前のプールが解放されたときに、そのオブジェクトが解放されたはずです。その参照カウントは2(1つ[UIColor colorWith...]は配列に追加するため)だったので、プールが空になるとすぐに2つのリリースメッセージを受信する[[self.nsBackColor objectAtIndex:x] objectAtIndex:y]はずであり、現在の反復でそれを置き換えるまで、ポインターはぶら下がったままにする必要があります。へのポインタcolor

明らかに、それは本来あるべき方法、または私が理解している方法で正確に起こっているわけではありません。ただし、@autoreleasepool {}ディレクティブは明らかに見当違いです。ループの周りにあるwhile (true)か、スレッドのプールを優先して完全に削除する必要があります。

于 2013-02-27T10:03:33.410 に答える