im having problems with leak memory. The instruments show line "pagamento_" is a malloc. i dont have idea how resolve this.
i have following code: * dados is NSMutableArray, and im alloc in other place... and do release in dealloc.
NSString *path = [self caminho];
if (sqlite3_open([path UTF8String], &Banco) == SQLITE_OK){
if (sqlite3_prepare_v2(Banco, [sql UTF8String], -1, &stmt, NULL) == SQLITE_OK) {
int row = sqlite3_step(stmt);
while(row == SQLITE_ROW) {
...
if([tabela isEqual:#"Pagamento"]){
pagamento_ = [[Pagamento alloc]init];
pagamento_.codigo = sqlite3_column_int(stmt, 0);
pagamento_.codNomePgto = sqlite3_column_int(stmt, 1);
pagamento_.codCategoria = sqlite3_column_int(stmt, 2);
pagamento_.vencimento = [NSString stringWithUTF8String:(char *)sqlite3_column_text(stmt, 3)];
pagamento_.repeticaoPagamento = [NSString stringWithUTF8String:(char *)sqlite3_column_text(stmt, 4)];
pagamento_.dataTermino = [NSString stringWithUTF8String:(char *)sqlite3_column_text(stmt, 5)];
pagamento_.vctoFDS = [NSString stringWithUTF8String:(char *)sqlite3_column_text(stmt, 6)];
pagamento_.valorPrevisto = [NSString stringWithFormat:#"%4.2f",sqlite3_column_double(stmt, 7)];
pagamento_.valorPago = [NSString stringWithFormat:#"%4.2f",sqlite3_column_double(stmt, 8)];
pagamento_.dataPgto = [NSString stringWithUTF8String:(char *)sqlite3_column_text(stmt, 9)];
pagamento_.anotacoes =[NSString stringWithUTF8String:(char *)sqlite3_column_text(stmt, 10)];
pagamento_.debitoAutomatico = [NSString stringWithUTF8String:(char *)sqlite3_column_text(stmt, 11)];
pagamento_.nome = [NSString stringWithUTF8String:(char *)sqlite3_column_text(stmt, 12)];
pagamento_.numSerie = sqlite3_column_int(stmt, 13);
pagamento_.codFavorecido = sqlite3_column_int(stmt, 14);
pagamento_.favorecido =[NSString stringWithUTF8String:(char *)sqlite3_column_text(stmt, 15)];
pagamento_.valor = [NSString stringWithFormat:#"%4.2f",sqlite3_column_double(stmt, 16)];
[dados addObject:pagamento_];
[pagamento_ release];
}
row = sqlite3_step(stmt);
}
sqlite3_finalize(stmt);
sqlite3_close(Banco);
return [dados copy];
anybody know how i resolve this??
thanks
return [dados copy];
This is causing a leak since you aren't releasing the original array. Since dados is an NSMutbaleArray that is, in theory, allocated in your -init and released in your -dealloc, copying dados on return from the code above is a good idea, but you should use:
return [[dados copy] autorelease];
If your application is crashing when you just return dados (or when you do the above), it is because you aren't managing memory correctly. As suggested by Ram, use the static analyzer and fix any problems it identifies first (build and analyze in Xcode on Snow Leopard).
If your app still crashes, then turn on NSZombies (google can show you how) and see if that catches it.
Unless you need to target iPhone OS 2.x or have a really really esoteric need to do so, you should use Core Data instead of SQLite. It'll undoubtedly be faster and save you significant development time.
You're properly releasing pagamento_ after adding it to the dados array, but you're returning a copy of dados from this method. That is most likely a mistake. Unless the caller of this method knows to release that array, it will be leaked, causing the pagamento_ object to be leaked as well. You probably should do this:
return [[dados copy] autorelease];
You almost certainly want to return [[dados copy] autorelease]. Just returning the result of copy will normally be a memory leak under the Cocoa memory management rules.
Try using the LLVM Clang Static analyser, for details see this link
Related
I have retrieved data from sqlite3 database table as below
NSString *name = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)];
NSString *price = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
now I have an NSMutableArray named as Data, I have declared and synthesized it properly, now how can I add values into it, I tried addObject, and print in NSLog, but showing null value, while there are values in name and price?
help me out
If the array is nil, it will never accept values because it doesn't exist. Even if you synthesize a property, it doesn't mean the property gets a default object assigned to it. Somebody still has to make sure an instance of NSMutableArray exists.
NSNumber *WId;
int temp1 = (int)sqlite3_column_int(walkstatement, 0);
WId = [[NSNumber alloc] initWithInt:temp1];
char *WNameCharacter;
WNameCharacter = (char *) sqlite3_column_text(walkstatement, 1);
NSString *WNameString = [[NSString alloc] initWithUTF8String:WNameCharacter];
NSMutableDictionary *tempWalk = [[NSMutableDictionary alloc] init];
[tempWalk setObject:WId forKey:#"WalkId"];
[tempWalk setObject:WNameString forKey:#"WalkName"];
[regionWalkArray addObject:tempWalk];
This worked for me please change the variables according to your requirement..
NSString *strSql = #"select tblrecentsearch_id,xmlrequest,company,postcode,city,kilometer,date from tblrecentsearch";
returnValue = sqlite3_prepare_v2(database, [strSql UTF8String], -1, &selectStatement, NULL);
if(returnValue == SQLITE_OK)
{
arrRecentSearch=[[NSMutableArray alloc] init];
while(sqlite3_step(selectStatement)==SQLITE_ROW)
{
Search *ObjSearch = [[Search alloc]init];
ObjSearch.intRecentSearchId = sqlite3_column_int(selectStatement, 0);
ObjSearch.xmlRequest = [NSString stringWithCString:(char *)sqlite3_column_text_check(selectStatement, 1) encoding:NSUTF8StringEncoding];
ObjSearch.strCompnay=[NSString stringWithCString:(char *)sqlite3_column_text_check(selectStatement, 2) encoding:NSUTF8StringEncoding];
ObjSearch.strPostCode=[NSString stringWithCString:(char *)sqlite3_column_text_check(selectStatement, 3) encoding:NSUTF8StringEncoding];
ObjSearch.strPlace = [NSString stringWithCString:(char *)sqlite3_column_text_check(selectStatement, 4) encoding:NSUTF8StringEncoding];
ObjSearch.strKilometer = [NSString stringWithCString:(char *)sqlite3_column_text_check(selectStatement, 5) encoding:NSUTF8StringEncoding];
ObjSearch.strDate = [NSString stringWithCString:(char *)sqlite3_column_text_check(selectStatement, 6) encoding:NSUTF8StringEncoding];
[arrRecentSearch addObject:ObjSearch];
[ObjSearch release];
}
}
sqlite3_finalize(selectStatement);
I want release arrRecentSearch but it will return from function . How can i realese this array. Please help me.I am fetching data from databse.
just autorelease it :
return [arrRecentSearch autorelease];
Have a look at the apple memopry management guidelines for more information on how this works
If you are going to return an autoreleased object, you must remember to retain it if you wnat to keep it around later. i.e. if we have a function that returns an autoreleased array
- (NSArray *) getSearchResults {
return [[[NSArray alloc] init] autorelease];
}
and you want to remember the search results for later you must remember to do this :
...
NSArray *results = [[self getSearchResults] retain]; //!< Remember the retain here!
...
or, you might use a property to store it :
#property (nonatomic, copy) NSArray *searchResults;
...
self.searchResults = [self getSearchResults]; //!< The property handles the retain for you here
...
Either way, if you just leave it as autoreleased, it's going to vanish and you're going to get an exception!
EDIT: Just realised MustISignUp has answered this in a comment!
I have a very strange memory leak problem, it seems that sqlite3_step is doing some nasty stuff :|
I spent almost 4 hours trying to fix this but no luck till now :(
Here it is the code:
[dbList removeAllObjects];
sqlite3_stmt *statement = nil;
const char *sql = "SELECT * FROM dbs ORDER by rowOrder;";
if (sqlite3_prepare_v2(dbHandler, sql, -1, &statement, NULL) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
DatabaseEntry *entry = [[DatabaseEntry alloc] init];
entry.databaseID = sqlite3_column_int(statement, 0);
entry.databaseTitle = [NSString stringWithFormat:#"%s", (char *)sqlite3_column_text(statement, 1)];
entry.databaseProtected = sqlite3_column_int(statement, 3);
entry.databaseFileName = [NSString stringWithFormat:#"%s", (char *)sqlite3_column_text(statement, 2)];
entry.databaseOrder = sqlite3_column_double(statement, 4);
[dbList addObject:entry];
[entry release];
}
}
sqlite3_finalize(statement);
The problem seems to be with my query, if I remove the "ORDER by rowOrder" part, everything seems to be just fine, also I'm using sqlcipher, and I'm wondering if that might cause this leak ?!
Thanks a lot for your attention !!!
Update: Hey Andy, I was wrong. I started looking into this more closely after running through some scenarios in Leaks. It looks like a bad merge from the upstream SQLite source missed two pager cleanup calls. The issue caused page cache to remain allocated after the pager was closed. It probably wouldn't affect most programs, but I would still definitely recommend pulling down the latest source code that fixes the issue from GitHub at http://github.com/sjlombardo/sqlcipher
I am developing a app for a movie in which I need to fetch data from the database considering some constraints. It works perfectly on the first occasion, but when I try to fetch data 2nd time it throws a runtime exception( the app crashes).I have to bind 3 placeholders. 2 are text and 1 is integer type. Here's the code which I am using to fetch data from the database.
-(void) Data2
{
databaseName = #"Cinema1.sqlite";
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath =[documentsDir stringByAppendingPathComponent:databaseName];
[self checkAndCreateDatabase];
sqlite3 *database;
if (sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK)
{
if(detailStmt == nil)
{
const char *sql = "Select PVR,Fame,Cinemax,Big from listing where UPPER(State) = UPPER(?) and UPPER(City) = UPPER(?) and ZIP = ?";
if(sqlite3_prepare_v2(database, sql, -1, &detailStmt, NULL) == SQLITE_OK)
{
NSLog(#"Hiiiiiii");
sqlite3_bind_text(detailStmt, 1, [t1 UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(detailStmt, 2, [t2 UTF8String], -2, SQLITE_TRANSIENT);
sqlite3_bind_int(detailStmt, 3, t3);
if(SQLITE_DONE != sqlite3_step(detailStmt))
{
NSLog(#"Helllloooooo");
NSString *pvr= [NSString stringWithUTF8String:(char *)sqlite3_column_text(detailStmt, 0)];
NSString *fame= [NSString stringWithUTF8String:(char *)sqlite3_column_text(detailStmt, 1)];;
NSString *cinemax = [NSString stringWithUTF8String:(char *)sqlite3_column_text(detailStmt, 2)];
NSString *big= [NSString stringWithUTF8String:(char *)sqlite3_column_text(detailStmt, 3)];
pvr1 = pvr;
fame1 = fame;
cinemax1 = cinemax;
big1 = big;
NSLog(#"PVR %# Fame %# Cinemax %# Big %#",pvr1,fame1,cinemax1,big1);
}
}
sqlite3_finalize(detailStmt);
}
}
sqlite3_close(database);}
Can anyone help me with this.
You are using the sqlite3_prepare_v2() and sqlite3_finalize() wrong. You only prepare a statement once and then you can bind values to it as much as you'd like. When you're done you call sqlite3_reset(). When you're completely done with this statement and won't ever use it again (i.e. you quit the app), then you use finalize.
Your app crashes because you finalize the statement, but the pointer detailStmt still points to the position where your statement once was, and tries to access that region of the memory.
See also here: http://www.sqlite.org/c3ref/prepare.html
As Toby points out, the variables pvr, fame, cinemax, and big (and the reassigned pvr1, fame1, cinemax1, and big1) are autoreleased when returned from -stringWithUTF8String:, but you never retain them. Any access to these variables after this point will cause a crash.
You say that you are seeing a thrown exception. It might be helpful to know what that exception is, by examining the console output. Also, you can enable a breakpoint on objc_exception_throw in libobjc.A.dylib, then debug with breakpoints on, to find the exact line at which this exception occurs.
In my limited Iphone experience when something runs once and then crashes on the next iteration, generally you are releasing memory you shouldnt be or not releasing memory you should be. Try looking at your memory allocations for problems.
I am having a problem with what I believe is a memory leak which after some time is causing my app to slow down. I have a sectioned uitableview that has sections of 'movie directors' with rows of thier movies in their particular section. To do this I am calling a data object (and passing it the section header) to return that section's data and populate the section rows. So I am calling that object a few times on the same view(numberOfRowsInSection, cellForRowAtIndexPath, and didSelectRowAtIndexPath) this happens for each section. Looking at Instruments, I believe the leak is coming from getDirectorsMovies:theDirector from Movies.m. Can anyone tell me what I am doing that is causing this leak. Any help would be greatly appreciated, I've been working on this for a few weeks. Below is some code to show what I am doing.
Thanks in advance!!!
//Movies.h
#import <Foundation/Foundation.h>
#import <sqlite3.h>
#import "Movie.h"
#interface Movies : NSObject {
}
- (NSMutableArray *) getDirectorsMovies:(NSString *)theDirector;
#end
//Movies.m //getDirectorsMovies:(NSString *)theDirector goes to the database, gets the directors movies, and returns them in an array
#import "Movies.h"
#implementation Movies
- (NSMutableArray *) getDirectorsMovies:(NSString *)theDirector
{
sqlite3 *database;
NSString *databaseName = #"Movies.sql";
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
NSString *databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
NSMutableArray *theDirectorsMovies = [[NSMutableArray alloc] init];
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
const char *sqlStatement = "select * from movies where lastname = ? order by lastname, movie";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
sqlite3_bind_text(compiledStatement, 1, [theDirector UTF8String], -1, SQLITE_TRANSIENT);
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
NSString *aLastName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
NSString *aDirector = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 2)];
NSString *aMovie = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 3)];
Movie *movie = [[Movie alloc] initWithName:aMovie lastname:aLastName director:aDirector];
[theDirectorsMovies addObject:movie];
[movie release];
}
}
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
return theDirectorsMovies;
[theDirectorsMovies release];
}
#end
//Calling getDirectorsMovies:(NSString *)theDirector
MoviesAppDelegate *appDelegate = (MoviesAppDelegate *)[[UIApplication sharedApplication] delegate];
Director *director = (Director *)[appDelegate.director objectAtIndex:indexPath.section];//appDelegate.director IS A MSMutableArray defined in the AppDelegate
self.theMovies = nil;//THIS IS A MSMutableArray defined in the AppDelegate
Movies *directorMovies = [[Movies alloc] init];
self.theMovies = [directorMovies getDirectorMovies:director.lastname];
[directorMovies release];
Movie *movie = (Movie *)[theMovies objectAtIndex:indexPath.row];
//do whatever with the data
[movie release];
You have this:
return theDirectorsMovies;
[theDirectorsMovies release];
Nothing happens after the return statement, so your call to release will never happen. It was for this very reason that AutoreleasePools were invented (and patented). Simply do:
return [theDirectorsMovies autorelease];
And your memory leak will go away.
There are a number of potential issues here it would be useful to see the init method for Movie as that may be where the issue is. Also you should have an autorelease on the NSMutableArray.
In my sqlite code I have the following statement normally before the sqlite3_finalize call
sqlite3_clear_bindings(compiledStatement);
That call cleared up a lot of issues for my code.