0

2つの問題があります

1) 私のアプリは、最初の数回の実行でデバイス上で正常に動作します。次に、最初の画面がポップアップした後 (Tab BAr) にクラッシュします。デバイスを MAC に接続してデバイス アプリを実行すると、動作します (デバッグ モードではありません)。

クラッシュ ログを確認したところ、"EXC_BAD_ACCESS (SIGSEGV)" の cos がクラッシュし、Thread0 がクラッシュしました。エラーは、割り当て解除されたオブジェクトを解放した NSAutorelease でした。

2) シミュレーターで計測器を使用してアプリを実行しました。この関数呼び出しで多くのリークが見られます。これがサンプルコードです。Instrumentsを使用して実行すると、「setObject」行にリークが表示されます。

//クラス A - NSObject のサブクラス

+(NSMutableDictionary *)Hello {

 NSMutableDictionary *dctONE = [[NSMutableDictionary alloc]initWithCapacity:0];
 NSMutableArray *arrKeys = [[NSMutableArray alloc] initWithCapacity:0];

    [arrKeys addObject:@"Object1"];
 [arrKeys addObject:@"Object2"];

    [dctONE setObject:[NSString stringWithFormat:@"dsfsdf"] forKey:[arrKeys          objectAtIndex:0]];
 [dctONE setObject:[NSString stringWithFormat:@"dsfsdf"] forKey:[arrKeys objectAtIndex:1]];

    [arrKeys release];
    return dctONE;

}

/// クラス B

-(void)some_Function {
 NSMutableDictionary * dct = [A Hello];   //all declarations are done

 //do stuff with dct
 [dct release];
}

なぜ「setObject」でリークするのですか?? 私はすべてを正しくリリースしていますか?[NSString stringWithFormat:] だけですが、それは自動解放ですよね??

これは私を夢中にさせていますか?

2つの問題は関連していますか?? PS: SIM 上ではクラッシュせず、奇妙にもデバイスを MAC に接続してからデバイス上でテストしてもクラッシュしません (デバッグではなく、デバイス上のアプリを直接クリックします)。

編集:

-(NSMutableDictionary *) ExecuteDataSet:(NSString *)strQuery
{
    NSMutableDictionary  *dctResult = [[[NSMutableDictionary alloc] init] autorelease];
//  BOOL isSucess = FALSE;

const char *sql = [strQuery UTF8String];
sqlite3_stmt *selectStatement;

//prepare the select statement
int returnValue = sqlite3_prepare_v2(database, sql, -1, &selectStatement, NULL);
if(returnValue == SQLITE_OK)
{
    sqlite3_bind_text(selectStatement, 1, sql, -1, SQLITE_TRANSIENT);
    //loop all the rows returned by the query.
    NSMutableArray *arrColumns = [[NSMutableArray alloc] init];
    for (int i=0; i<sqlite3_column_count(selectStatement); i++) 
    {
        const char *st = sqlite3_column_name(selectStatement, i);
        [arrColumns addObject:[NSString stringWithCString:st encoding:NSUTF8StringEncoding]];
    }
    int intRow =1;
    while(sqlite3_step(selectStatement) == SQLITE_ROW)
    {
        NSMutableDictionary *dctRow = [[NSMutableDictionary alloc] init];
        for (int i=0; i<sqlite3_column_count(selectStatement); i++)                 
        {
            int intValue = 0;
            const char *strValue;
            switch (sqlite3_column_type(selectStatement,i)) 
            {
                case SQLITE_INTEGER:
                    intValue  = (int)sqlite3_column_int(selectStatement, i);
                    [dctRow setObject:[NSString stringWithFormat:@"%d",intValue] forKey:[arrColumns objectAtIndex:i]];                      
                    break;

                case SQLITE_TEXT:
                    strValue = (const char *)sqlite3_column_text(selectStatement, i);
                    [dctRow setObject:[NSString stringWithCString:strValue encoding:NSUTF8StringEncoding] forKey:[arrColumns objectAtIndex:i]];                     
                    break;

                default:
                    strValue = (const char *)sqlite3_column_value(selectStatement, i);
                    [dctRow setObject:[NSString stringWithCString:strValue encoding:NSUTF8StringEncoding] forKey:[arrColumns objectAtIndex:i]];
                    break;
            }

        }
        [dctResult setObject:[dctRow retain] forKey:[NSString stringWithFormat:@"Table%d",intRow]];
        intRow ++;
        [dctRow release];
    }
    [arrColumns release];
}
return dctResult;

}

4

2 に答える 2

1

で不要な作業を大量に実行しています+Hello。デバッグの最初のステップは、常に不必要な複雑さを取り除くことです。次のようにしてみてください。

+(NSMutableDictionary *)Hello {

     NSMutableDictionary *dctONE = [NSMutableDictionary dictionaryWithObjectsAndKeys:
         @"dsfsdf", @"Object1", @"dsfsdf", @"Object2", nil];

     return dctONE;
}

そのNSMutableDictionary dictionaryWithObjectsAndKeysメソッドは、オブジェクト、キー、オブジェクト、キーに続く nil で終わる配列を取ります。これは、自動解放された NSMutableDictionary オブジェクトを返します。これは、返したいものです。

この世界には保証はありませんが、メソッドがリークしないことはほぼ保証できます。

于 2010-09-28T12:22:40.033 に答える
1

リークは次の行にあるようです。

[dctResult setObject:[dctRow retain] forKey:[NSString stringWithFormat:@"Table%d",intRow]];

setObjectは格納するオブジェクトを呼び出しretainますが、実際には手動で保持しているため、保持カウントは 1 ではなく 2 になり、dctResult解放されてもメモリから削除されません。

于 2010-09-28T12:09:12.383 に答える