Нужна помощь в поиске утечки памяти при копировании базы данных Sqlite в изменяемый массив - PullRequest
0 голосов
/ 17 августа 2010

Кажется, у меня утечка в 1,19 КБ где-то в следующем коде. открывая дерево вызовов в инструментах, я сузил утечки до следующего:

61,8% утечек происходят из + [NSString stringWithUTF8String:]

38,1% утечек происходят из + [NSNumber numberWithDouble:]

-(void) readMinesFromDatabase 
{
    NSLog(@" Setup the database object");
    sqlite3 *database;

    // Init the  Array
    northernMines = [[NSMutableArray alloc] init];
    nCentralMines = [[NSMutableArray alloc] init];
    centralMines = [[NSMutableArray alloc] init];
    southernMines = [[NSMutableArray alloc] init];
    //NSLog(@" pre if statement");
    // Open the database from the users filessytem
    if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) 
{
    // Setup the SQL Statement and compile it for faster access
    const char *sqlStatement = "SELECT * FROM mines";
    //NSLog(@"pre 2nd if statement");
    sqlite3_stmt *compiledStatement;

    if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) != SQLITE_OK) 
{
        NSLog( @"Error: Failed to prepare stmt with message %s", sqlite3_errmsg(database));
    }
    else 
{
        // Loop through the results and add them to the feeds array
        NSLog(@"pre loop");
        while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
            NSString *name;
            NSString *com;
            NSString *county;
            NSNumber *lat;
            NSNumber *longit;
            // Read the data from the result row
            //deals with null strings in the name and commodity fields of the database
            //NSLog(@"ered the loop");
            if (sqlite3_column_text(compiledStatement, 3) != NULL) {
                name = [NSString  stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 3)];
            } 
            else {
                name = @"";
            }
            if (sqlite3_column_text(compiledStatement, 10) != NULL) {
                com = [NSString  stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 10)];
            } 
            else {
                com = @"";
            }
            //latitude and longitudes
            lat = [NSNumber numberWithDouble:(double )sqlite3_column_double(compiledStatement, 4)];
            longit = [NSNumber numberWithDouble:(double )sqlite3_column_double(compiledStatement, 5)];
            //NSLog(@"long %@",longit);
            // Create a new  object with the data from the database
            Mine *mine = [[Mine alloc] initWithMineName:name latitudeInitial:lat longitudeInitial:longit commodity:com];

            // Add the object to the animals Array
            county = [NSString  stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 8)];

            if([county isEqualToString:@"Butte"] || [county isEqualToString:@"Plumas"] || [county isEqualToString:@"Yuba"] || [county isEqualToString:@"Sierra"])
            {
                [northernMines addObject:mine];
            }
            else if([county isEqualToString:@"Nevada" ]|| [county isEqualToString:@"Placer"] || [county isEqualToString:@"El Dorado"] || [county isEqualToString:@"Sutter"])
            {
                [nCentralMines addObject:mine];

            }
            else if([county isEqualToString:@"Amador"] || [county isEqualToString:@"Sacramento"] || [county isEqualToString:@"Calaveras"] || [county isEqualToString:@"San Joaquin"] || [county isEqualToString:@"Stanislaus"])
            {
                [centralMines addObject:mine];
            }
            else if([county isEqualToString:@"Tuolumne"] ||[county isEqualToString:@"Mariposa"] || [county isEqualToString:@"Madera"] || [county isEqualToString:@"Merced"])
            {
                [southernMines addObject:mine];
            }
            else
            {

            }
            [mine release];
            //[name release];
            //[com release];
            //[county release];                        
            //[lat release];
            //[longit release];

        }
        NSLog(@"done with loop");
        //[mines addObject:@"nil"];

    }
    // Release the compiled statement from memory
    sqlite3_finalize(compiledStatement);


}
sqlite3_close(database);
}

Файл реализации шахтного объекта:

#import "Mine.h"

@implementation Mine
@synthesize mineName, latitudeInitial, longitudeInitial, commodity;
-(id)initWithMineName:(NSString *)n latitudeInitial:(NSNumber *)l longitudeInitial:(NSNumber *)g commodity:(NSString *)c 
{
    self.mineName = n;
    self.latitudeInitial = l;
    self.longitudeInitial = g;
    self.commodity = c;
    return self;
}

@end

Ответы [ 2 ]

1 голос
/ 17 августа 2010

Ну, это немного сложно сказать из-за отступа, где заканчивается функция (это вся функция?), Но я полагаю, что вы забыли освободить 4 массива, которые вы выделяете в начале функции. При утечке массивов вы также теряете их содержимое.


Редактировать - для добавленного вами кода инициализатора:

Я не уверен, что это как-то связано с утечками памяти, но я заметил, что инициализатор не реализован правильно:

  • Вы должны позвонить init на super и обновить self (подробнее здесь )

  • в этом я не уверен на 100%, но я думаю, что вы не должны посылать сообщения (вызовы методов) текущему объекту изнутри метода init, и, используя точечную запись, вы фактически вызываете методы установки (но опять же, я не совсем уверен в этом)

Я предполагаю, что свойства объявлены как (retain), и вы освобождаете их в методе dealloc. Что было бы правильно.

Я действительно не вижу ничего плохого в коде, который вы показали. Может быть, проблема не совсем здесь (просто идея).


Редактировать 2 - пример инициализатора

Вам следует потратить некоторое время на чтение документации Apple , в ней много примеров.

Вот моя версия (надеюсь, в ней не так много ошибок):

-(id)initWithMineName:(NSString *)n latitudeInitial:(NSNumber *)l longitudeInitial:(NSNumber *)g commodity:(NSString *)c {

    // Assign self to value returned by super's designated initializer

    // Designated initializer for NSObject is init

    self = [super init];

    if (self) {

        mineName = [n retain];
        latitudeInitial = [l retain];
        longitudeInitial = [g retain];
        commodity = [c retain];

    }

    return self;
}
0 голосов
/ 17 августа 2010

Просто мысль, но может ли утечка памяти быть в инициализаторе объекта Mine (- [Mine initWithMineName: latitudeInitial: longitudeInitial: commodity:]) ??

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