views:

377

answers:

5

I'm trying to build a class for handling all sqlite3 work and I've encountered an EXC_BAD_ACCESS which I just can't explain. I am new to Objective-C development and memory management in general so I apologize if this is a stupid question.

When initializing the class I get the path to the database file and keep it around:

NSArray * documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
databasePath = [[[documentPaths objectAtIndex:0] stringByAppendingPathComponent:@"Database.sql"] retain];

Then I try to use it and it crashes on me:

if (sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) { // crashes

The odd thing is that the exact same line in a different function works perfectly. I tried adding the variable initialization to above the line, but to no avail:

NSArray * documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
databasePath = [[[documentPaths objectAtIndex:0] stringByAppendingPathComponent:@"Database.sql"] retain];

if (sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) { // crashes

In both cases the retain count is 2.

However, putting any form of static text in there works fine:

databasePath = @"I have a balloon";
if (sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) { // fine
// or
if (sqlite3_open([@"APPLES!" UTF8String], &database) == SQLITE_OK) { // fine

A little more experimentation revealed that it was the UTF8String function that was crashing, but I don't understand why.

Edit: Even more experimentation resulted in me being able to call the UTF8String function but not even use the results:

const char * test = [databasePath UTF8String];
NSLog(@"%@", [NSString stringWithUTF8String:test]); // fine
if (sqlite3_open(test, &database) == SQLITE_OK) { // fails

Edit: Messed around even more and discovered that the problem was in a parameter that I was passing to the function. I had breakpoints all over the place so I was 100% sure that the point it fails is at the line I specified, a line which doesn't use the passed variable, but somehow it caused everything to fail. Sometimes. I have no idea how it went wrong, but I rewrote the entire thing, changed my function call and now it works.

Thanks to all who answered.

A: 

Try a copy instead of a retain on the variable - it'll make an immutable copy of the string so it shouldn't go changing or disappearing.

EDIT::

What happens when you simply type

if (sqlite3_open[@"myDatabase.sqlite" UTF8String], &database) == SQLITE_OK) {

Also are you sure that the

NSArray * documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
databasePath = [[[documentPaths objectAtIndex:0]
stringByAppendingPathComponent:@"Database.sql"] retain];

is actually returning where the database is?

The code I use to grab the database from the app directory where kFilename is the database file is:

- (NSString *)dataFilePath{

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];

    return [documentsDirectory stringByAppendingPathComponent:kFilename];
}

and then to use it I do:

if(sqlite3_open([[self dataFilePath] UTF8String], &database) != SQLITE_OK){

This works on both my iPod touch and the iPhone simulator.

EDIT2::

I've just used your above method and it seems to work here - I know it sounds stupid but have you tried rebooting? Its possible something strange is happening with the simulator

James Raybould
It doesn't make any difference. Copying the string that is made when finding the directory doesn't help, neither does copying the string just before I use it.
+1  A: 

Have you checked the contents of the databasePath variable before the open call is made? Add an NSLog statement, or use the debugger, to find its value – it could be either NULL, which may not be handled by the sqlite3_open function, or it could even be that the crash is because the path is valid, and the database it points to is corrupt.

Ciarán Walsh
It's full of contents. I tested the _UTF8String_ function and got results out of that too, but once I try passing anything to the sqlite3 function it crashes.
And what is the contents…? If you pass it as a constant string, does it still crash?
Ciarán Walsh
+1  A: 

My guess is that the database variable is not declared properly. It doesn't seem to have anything to do with the path to the database.

Did you declare database like this?:

sqlite3 *database;
Philippe Leybaert
Yeah, right above the line that crashes. I didn't think to add it since I deduced that the string was the problem.
+1  A: 

I suspect you are chasing the wrong problem. You haven't shown a crash dump but claim that opening "APPLES!" is 'fine' which sounds odd - surely you don't have a database with that name?

Are you sure you don't have a bad database file lying around - ie, the database file you are trying to open is corrupted in some way?

Jeff Laing
+1  A: 

I think you have to post the crash log, your crash makes no sense. The code you posted should work.

Kendall Helmstetter Gelner