0

計測器は、次のコードでメモリ リークを示しています。どこでも保持カウントが維持されていることを確認しました。自動解放プールも追加しましたが、まだメモリリークがあります。これを解決するには?

コードブロック:

- (NSArray *)lookupAllForSQL:(NSString *)sql
{
    sqlite3_stmt *statement;
    id result = nil;
    NSMutableArray *thisArray = [NSMutableArray arrayWithCapacity:4];
    statement = [self prepare:sql];
    if (statement)
    {
        while (sqlite3_step(statement) == SQLITE_ROW)
        {
            NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

            NSMutableDictionary *thisDict = [NSMutableDictionary dictionaryWithCapacity:4];
            for (int i = 0 ; i < sqlite3_column_count(statement) ; i++)
            {
                NSAutoreleasePool *poolInside = [[NSAutoreleasePool alloc] init];
                if(sqlite3_column_type(statement,i) == SQLITE_NULL)
                {
                    continue;
                }
                if (sqlite3_column_decltype(statement,i) != NULL &&
                    strcasecmp(sqlite3_column_decltype(statement,i),"Boolean") == 0)
                {
                    result = [NSNumber numberWithBool:(BOOL)sqlite3_column_int(statement,i)];
                }
                else if (sqlite3_column_type(statement,i) == SQLITE_INTEGER)
                {
                    result = [NSNumber numberWithInt:(int)sqlite3_column_int(statement,i)];
                }
                else if (sqlite3_column_type(statement,i) == SQLITE_FLOAT)
                {
                    result = [NSNumber numberWithFloat:(float)sqlite3_column_double(statement,i)];
                }
                else
                {
                    if((char *)sqlite3_column_text(statement,i) != NULL)
                    {
                        //result = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement,i)];
                        [thisDict setObject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement,i)]
                                     forKey:[NSString stringWithUTF8String:sqlite3_column_name(statement,i)]];
                        //[result release];
                        result = nil;
                    }
                }
                if (result)
                {
                    [thisDict setObject:result forKey:[NSString stringWithUTF8String:sqlite3_column_name(statement,i)]];
                }
                [poolInside drain];
            }
            [thisArray addObject:[NSDictionary dictionaryWithDictionary:thisDict]];
            [pool drain];
        }
    }
    sqlite3_finalize(statement);
    return thisArray;
}

計測器のスクリーンショット:

ここに画像の説明を入力

4

2 に答える 2

0

私は解決策を得ました。この関数は NSArray を返していましたが、これを適切にリリースしていませんでした。したがって、これらの変数はすべて、この関数ではなくメモリリークを引き起こしていました。

このビデオはそれを理解するのに役立ちました。

于 2013-05-30T16:26:48.110 に答える
0

発言が問題かと思いますcontinuecontinueステートメントにより、制御が最も近いループの次の反復に移動するため、条件が である場合、(sqlite3_column_type(statement,i) == SQLITE_NULL)制御trueは次の反復に渡され、「poolInside」プールは排出されません。だから私は使用します:

if(sqlite3_column_type(statement,i) == SQLITE_NULL)
{
    [poolInside drain];
    continue;
}

ただし、これはリークを解決しようとして追加したエラーである可能性があるため、@CodaFi からのコメントは引き続き有効です。

完全を期すために

リークの結果をすべて見てみると、次のpoolInside行がわかります。

[thisArray addObject:[NSDictionary dictionaryWithDictionary:thisDict]];

漏れるNSDictionaryたびにpoolInside漏れます。したがって、これは、返された配列にリークされたオブジェクトが含まれることを意味します。また、ネストされた NSAutoreleasePool をリークすると、 for ループ内で作成されたオブジェクトもリークされる可能性があると思われます。あなたが投稿した「Instruments Screenshot」はその動作を示していると思います。

于 2013-05-30T15:25:45.763 に答える