распределение памяти в запросах - PullRequest
0 голосов
/ 09 января 2012

У меня есть приложение, которое использует запросы данных и отображает их в UITableView. Пока все хорошо, я могу получить доступ к базе данных SQLite и отобразить данные в таблице, но после небольшого периода использования памяти моего приложения получил предупреждение. Уровень = 1 и закрыт. Используя инструменты анализа в поиске, я заметил, что данные моего приложения занимают разумное количество памяти.

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section  {

    tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;

    return [count count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath  {

    iMapDadosClientes *dadosClientes = (iMapDadosClientes *)[count objectAtIndex:indexPath.row];

    NSString *myIdent = @"myIdent";

    iMapGrid *grid = (iMapGrid *)[tableView dequeueReusableCellWithIdentifier:myIdent];

    tvDadosClientes.autoresizesSubviews = YES;

    if (grid == nil) {

        grid = [[[iMapGrid alloc] initWithFrame:CGRectZero reuseIdentifier:myIdent] autorelease];

        UILabel *label = [[[UILabel alloc] initWithFrame:CGRectMake(0.0, 0, 50.0, tableView.rowHeight)] autorelease];

        [grid addColumn:60];

        label.tag = TAG_1; 
        label.font = [UIFont systemFontOfSize:14.0]; 
        label.text = dadosClientes.cod;
        label.textAlignment = UITextAlignmentRight; 
        label.textColor = [UIColor blackColor]; 
        label.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleHeight; 

        [grid.contentView addSubview:label]; 

        label =  [[[UILabel alloc] initWithFrame:CGRectMake(70.0, 0, 20.0, tableView.rowHeight)] autorelease]; 

        [grid addColumn:100];

        label.tag = TAG_2; 
        label.font = [UIFont systemFontOfSize:14.0]; 
        label.text = dadosClientes.loja;
        label.textAlignment = UITextAlignmentCenter; 
        label.textColor = [UIColor blackColor]; 
        label.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleHeight; 

        [grid.contentView addSubview:label]; 

        label =  [[[UILabel alloc] initWithFrame:CGRectMake(110.0, 0, 350.0, tableView.rowHeight)] autorelease]; 

        [grid addColumn:470];

        label.tag = TAG_3; 
        label.font = [UIFont systemFontOfSize:14.0]; 
        label.text = dadosClientes.nome;
        label.textAlignment = UITextAlignmentLeft; 
        label.textColor = [UIColor blackColor]; 
        label.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleHeight; 

        [grid.contentView addSubview:label]; 

        label =  [[[UILabel alloc] initWithFrame:CGRectMake(480.0, 0, 240.0, tableView.rowHeight)] autorelease]; 

        [grid addColumn:730];

        label.tag = TAG_4; 
        label.font = [UIFont systemFontOfSize:14.0]; 
        label.text = dadosClientes.mun;
        label.textAlignment = UITextAlignmentLeft; 
        label.textColor = [UIColor blackColor]; 
        label.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleHeight; 

        [grid.contentView addSubview:label]; 

        label =  [[[UILabel alloc] initWithFrame:CGRectMake(740.0, 0, 20.0, tableView.rowHeight)] autorelease]; 

        [grid addColumn:768];

        label.tag = TAG_5; 
        label.font = [UIFont systemFontOfSize:14.0]; 
        label.text = dadosClientes.est;
        label.textAlignment = UITextAlignmentCenter; 
        label.textColor = [UIColor blackColor]; 
        label.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleHeight; 

        [grid.contentView addSubview:label]; 
    }

    UILabel *label_1 = (UILabel *)[grid.contentView viewWithTag:TAG_1];
    label_1.text = dadosClientes.cod;

    UILabel *label_2 = (UILabel *)[grid.contentView viewWithTag:TAG_2];
    label_2.text = dadosClientes.loja;

    UILabel *label_3 = (UILabel *)[grid.contentView viewWithTag:TAG_3];
    label_3.text = dadosClientes.nome;

    UILabel *label_4 = (UILabel *)[grid.contentView viewWithTag:TAG_4];
    label_4.text = dadosClientes.mun;

    UILabel *label_5 = (UILabel *)[grid.contentView viewWithTag:TAG_5];
    label_5.text = dadosClientes.est;

    return grid;
}

- (void) getInitialDataToDisplay:(NSString *)dbPath {

    count = [[NSMutableArray alloc] init];

    if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {

        const char *sql = "select cod, loja, nome, mun, est from apsa1010;";
        sqlite3_stmt *selectstmt;

        if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {

            while(sqlite3_step(selectstmt) == SQLITE_ROW) {

                iMapDadosClientes *dadosClientes = [[iMapDadosClientes alloc] cod:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 0)] loja:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)] nome:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 2)] pessoa:nil ender:nil bairro:nil mun:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 3)] est:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 4)] tel:nil bco1:nil risco:nil classe:nil lc:nil transp:nil ultCom:nil statCli:nil metr:nil salDup:nil uligTlv:nil dCompra:nil vend:nil celul:nil fax:nil email:nil contato:nil dtCada:nil priCom:nil dtNac:nil dtFunda:nil recno:nil];

                [count addObject:dadosClientes];

                [dadosClientes release];



                dadosClientes = nil;
            }
        }

        sqlite3_finalize(selectstmt);
    }
    else
        sqlite3_close(database); //Even though the open call failed, close the database connection to release all the memory.
}

- (void) finalizeStatements {

    if(database)
        sqlite3_close(database);
}

кто-то намекнул, что я могу делать неправильно в своем коде. Спасибо.

Ответы [ 2 ]

0 голосов
/ 09 января 2012

Не уверен, что это проблемы с памятью, но вот некоторые вещи, на которые стоит обратить внимание.

Всегда проверяйте коды возврата всех вызовов sqlite.Например, sqlite3_finalize имеет код возврата, как и sqlite3_close.Если финализация не удалась (например, занято), вам может потребоваться очистка в закрытом режиме (она не делает это для вас обязательно).Вот моя близкая функция:

if (_sqlite3)
{   
    int rc = sqlite3_close(_sqlite3);

    if (rc == SQLITE_BUSY) 
    {   
        sqlite3_stmt *stmt; 
        while ((stmt = sqlite3_next_stmt(_sqlite3, 0x00)) != 0) 
        {
            sqlite3_finalize(stmt); 
        }

        rc = sqlite3_close(_sqlite3);
    }

    if (rc != SQLITE_OK)
    {
        NSLog(@"close not OK.  rc=%d", rc);
    }

    _sqlite3 = NULL;
}

Помимо проблем с памятью, на которые вы должны обратить внимание:

  • prepare компилирует, что SQL-оператор может вернуть вам ссылку (& selectstmt inтвой случай).Вы не должны перекомпилировать это каждый раз.Вместо этого уберите ссылку и вызовите sqlite3_reset, прежде чем использовать ее снова, и не завершайте, пока не очистите эту область кода.Это позволяет вам снова и снова использовать один и тот же скомпилированный оператор из VBL - память должна оставаться стабильной.

  • Зачем открывать и закрывать каждый раз?Это не клиент SQL Server или что-то с пулом соединений.Оставьте это открытым, повторно используйте ваши скомпилированные операторы и используйте кеши и скомпилированные операторы.

0 голосов
/ 09 января 2012

Используйте инструменты для проверки на утечки и потерю памяти из-за оставшейся, но не утечки памяти.Последний является неиспользованной памятью, на которую все еще указывают.Используйте Heapshot в инструменте Allocations на инструментах.

Чтобы узнать, как использовать Heapshot для поиска разрыва памяти, см .: bbum blog

По сути, существует метод для запуска инструмента выделения инструментов,сделайте снимок кучи, запустите интуицию вашего кода и повторите повторение снимка кучи 3 или 4 раза.Это будет указывать на память, которая выделена и не освобождена во время итераций.

Чтобы выяснить результаты, откройте для просмотра отдельные распределения.

Если вам нужно увидеть, где происходят сохранения, релизы и авто-релизыдля объекта используйте инструменты:

Запустите инструменты, в Allocations включите «Record reference counts» on (вы должны остановить запись, чтобы установить опцию).Заставьте сборщик запустить, остановить запись, найти там ivar (datePickerView), выполнить детализацию, и вы сможете увидеть, где произошли все сохранения, выпуски и автоматические выпуски.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...