内存分配问题,设备iOS SDK 4.1崩溃(线程0崩溃)

时间:2010-09-28 09:52:27

标签: iphone memory-leaks device nsautoreleasepool

我有两个问题

1)我的应用程序在运行的前几次在设备上正常工作。然后在弹出第一个屏幕后崩溃(Tab BAr)。如果我将设备连接到我的MAC,然后运行设备应用程序,它可以工作(不是调试模式)。

我检查了崩溃日志,它崩溃了“EXC_BAD_ACCESS(SIGSEGV)”和Thread0崩溃。错误是NSAutorelease发布了一个解除分配的对象。

2)我使用模拟器上的仪器运行应用程序。它显示了此函数调用的大量泄漏。 这是一个示例代码。当我使用Instruments运行它时,它会在“setObject”行显示泄漏。

// NSObject的类A-子类

+(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:],但这是autorelease对吗??

这让我疯狂?

这两个问题有关吗? 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;

}

2 个答案:

答案 0 :(得分:1)

泄漏似乎在这一行:

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

setObject会在其存储的对象上调用retain,但您实际上是手动保留它,因此其保留计数将为2而不是1,并且当dctResult被释放时,它不会从内存中删除。

答案 1 :(得分:1)

你在+Hello做了大量不必要的工作。我调试的第一步始终是消除不必要的复杂性。试试这样:

+(NSMutableDictionary *)Hello {

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

     return dctONE;
}

NSMutableDictionary dictionaryWithObjectsAndKeys方法采用以nil结尾的数组,该数组包含对象,键,对象,键。它返回一个自动释放的NSMutableDictionary对象,这是你想要返回的对象。

在这个世界上没有任何保证,但我可以接近承诺你的方法不会泄漏。