Проблемы с выделением памяти, сбой на устройстве iOS SDK 4.1 (сбой потока 0) - PullRequest
0 голосов
/ 28 сентября 2010

У меня две проблемы

1) Мое приложение отлично работает на устройстве первые несколько раз его запуска. Затем он вылетает после всплывающего первого экрана (Tab BAr). Если я подключаю устройство к моему MAC, а затем запускаю приложение устройства, оно работает (не режим отладки).

Я проверил журналы аварий, произошел сбой, потому что «EXC_BAD_ACCESS (SIGSEGV)» и Thread0 аварийно завершился. Ошибка была в том, что NSAutorelease выпустил освобожденный объект.

2) Я запустил приложение, используя инструменты на симуляторе. Это показывает много утечек при вызове этой функции. Вот пример кода. Когда я запускаю его с помощью инструментов, он показывает утечку в строке "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:], но это автоматический выпуск, верно ??

Это сводит меня с ума?

Эти две проблемы связаны? PS: Это не дает сбой на SIM-карте, и, как ни странно, не дает сбой, даже когда я подключаю свое устройство к своему MAC и затем тестирую его на устройстве (не отлаживая, непосредственно нажимая на приложение на устройстве)

EDIT:

-(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 ]

1 голос
/ 28 сентября 2010

Вы делаете целую кучу ненужной работы в +Hello.Мой первый шаг в отладке - всегда удалять ненужные сложности.Попробуйте это так:

+(NSMutableDictionary *)Hello {

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

     return dctONE;
}

Этот метод NSMutableDictionary dictionaryWithObjectsAndKeys принимает массив с нулевым символом в конце, который содержит объект, ключ, объект, ключ.Он возвращает автоматически освобожденный объект NSMutableDictionary, который вы хотите вернуть.

В этом мире нет никаких гарантий, но я могу почти обещать, что этот метод не протечет.

1 голос
/ 28 сентября 2010

Утечка, кажется, находится в этой строке:

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

setObject вызовет retain для объекта, который он хранит, но вы фактически сохраняете его вручную, поэтому его счетчик хранения будет 2 вместо 1, а когда будет освобожден dctResult, он не будет удален из памяти.

...