tags:

views:

269

answers:

1

Hello,

I have the following function in my iPhone project which works great...unless the query returns nothing and then the app crashes. It is being a pain to debug with none of the breakpoints being activated at all!

I know this works as I pass in static stuff that is in the DB and it returns a value.

-(NSString *)getSomeText:(NSString *)toPass {
    sqlite3 *database;
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *databasePath = [documentsDirectory stringByAppendingPathComponent:@"sf.sqlite"];

    int strLength = 0;
    strLength = [toPass length];

    if (strLength <3)
        return @"Unknown";


    NSString *MIDstr;
    NSMutableString * toPass Copy = [NSMutableString stringWithString:toPass];
    MIDstr = [toPassCopy substringWithRange:NSMakeRange(0, 3)];


    // 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
        NSString *BaseSQL = [NSString stringWithFormat:@"select * from MIDS where MID = '%@'",MIDstr];
        NSLog(BaseSQL);

        const char *sqlStatement = [BaseSQL UTF8String];
        //NSLog(BaseSQL);
        sqlite3_stmt *compiledStatement;
        if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
            // Loop through the results and add them to the feeds array

            while(sqlite3_step(compiledStatement) == SQLITE_ROW) {


                    NSString *aName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
                    NSString *returnString = [NSString stringWithFormat:@"%@",aName];
                    return returnString;                

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

    }
    sqlite3_close(database);

}
+3  A: 

A. if sqlite3_step does not return any rows, you crash because you have declared that you are returning a NSString, but when there are no rows you return nothing. The caller will try to read a NSString from the stack and thus end up dereferencing garbage.

To quickly fix the problem, write:

    sqlite3_close(database);
    return nil;
}

and make sure the caller handles nil results.

B/ If you do have data, your code never gets to call *sqlite3_finalize* and *sqlite3_close* because you return early:

while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
    [..]
    return returnString;
diciu
Spot on thank you!Are you saying finalize and close before doing my return returnString?
Lee Armstrong
This is usually set up by declaring a local NSString, computing it and returning at the very end of the method, after any cleanup has been done. Btw, not returning values from a non-void methods is a compiler warning - you may want to read XCode's output more carefully or turn on "Treat Warnings as Errors"
diciu