Reputation:
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.
Upvotes: 0
Views: 1548
Reputation: 75058
I think you have to post the crash log, your crash makes no sense. The code you posted should work.
Upvotes: 1
Reputation: 275
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?
Upvotes: 1
Reputation: 5820
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
Upvotes: 0
Reputation: 171854
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;
Upvotes: 1
Reputation: 1866
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.
Upvotes: 1