A memory leak in simpleftp - iphone

I use simpleFTP to request document information. I detect memory-leak with instrument as below:
And in the call tree I find out where is the memory leak happened:
The method "_parseListData" as below:
- (void)_parseListData
{
NSMutableArray * newEntries;
NSUInteger offset;
// We accumulate the new entries into an array to avoid a) adding items to the
// table one-by-one, and b) repeatedly shuffling the listData buffer around.
newEntries = [NSMutableArray array];
assert(newEntries != nil);
offset = 0;
do {
CFIndex bytesConsumed;
CFDictionaryRef thisEntry;
thisEntry = NULL;
assert(offset <= self.listData.length);
bytesConsumed = CFFTPCreateParsedResourceListing(NULL, &((const uint8_t *) self.listData.bytes) [offset], self.listData.length - offset, &thisEntry);
if (bytesConsumed > 0) {
........
}
I don't know how to fix this problem.
The method "CFFTPCreateParsedResourceListing" is a system method and it create __NSDate (look at the second pic).
This is where the memory-leak happen.

The CFFTPCreateParsedResourceListing function returns a CFDictionary into the thisEntry variable, which presumably contains the NSDate objects.
The code should call CFRelease on thisEntry once it is finished with it:
// once we're done with thisEntry
if (thisEntry) {
CFRelease(thisEntry);
}

Old post, but useful solution. You can find the answer here BlackRaccoon ftp client.
According to the creator the CFFTPCreateParsedResourceListing method retains twice the NSDate, to override the issue add the next code, be aware of the comments here:
FAQ section
"Actually, in WhiteRaccoon, if you list a directory you will leak NSDate's. The function CFFTPCreateParsedResourceListing in Apple's SDK has a leak in it. I've attempted to "patch" this, however it isn't guaranteed to work. For OS 5.1 it does work."
........
if (parsedBytes > 0)
{
if (listingEntity != NULL)
{
//----- July 10, 2012: CFFTPCreateParsedResourceListing had a bug that had the date over retained
//----- in order to fix this, we release it once. However, just as a precaution, we check to see what
//----- the retain count might be (this isn't guaranteed to work).
id date = [(__bridge NSDictionary *) listingEntity objectForKey: (id) kCFFTPResourceModDate];
if (CFGetRetainCount((__bridge CFTypeRef) date) >= 2)
CFRelease((__bridge CFTypeRef) date);
this works for me

Related

Unsolvable memory leak IPhone

I am new to IPhone programming and am I having trouble solving the following memory leak.
while(numDeckCounter < numDecks){
int cardCounter=1;
for (int i =1; i<=52; i++) {
tempCard = [Card new]; //leaks tool says that this is leaking object
if(i>=1 && i<=13)
{
tempCard.suit = CLUBS;
tempCard.faceValue = cardCounter;
[deckArr addObject:tempCard]; //reference count 2
cardCounter++;
}
else if(i>=14 && i<=26)
{
tempCard.suit = DIAMONDS;
tempCard.faceValue = cardCounter;
[deckArr addObject:tempCard];
cardCounter++;
}
else if(i>=27 && i<=39)
{
tempCard.suit = HEARTS;
tempCard.faceValue = cardCounter;
[deckArr addObject:tempCard];
cardCounter++;
}
else
{
tempCard.suit = SPADES;
tempCard.faceValue = cardCounter;
[deckArr addObject:tempCard];
cardCounter++;
}
if(cardCounter ==14){
cardCounter=1;
}
[tempCard release]; //this causes an EXC_BAD_ACCESS -reference count should be 1
}
numDeckCounter++;
}
I was under the impression that adding an object to the array would increase its reference count by one, then it would be safe to release the object you just added because it would not be deallocated until the array was released bumping which would then release each object in the array. This is when the object should finally be deallocated.
When I add the [tempCard release]; it crashes my app because it can't access the memory location because it has already been deallocated.
From everything I have read, I think what I said above is true. Someone please correct me if I am wrong. Thanks.
I don't see any leaks in the code you presented. (There are some opportunities to slim it down, though, say by moving the identical operations out of the conditionals).
The Leaks tool output is pretty tricky to read. Is it possible that the Card object is leaking one of it's ivars?
Instead of leaks, run static analysis on your product (Product->Analyze). I think it will flag a different part of your code.
Perhaps try [[Card alloc] init] instead of [Card new]. This is just a guess. However trying the IMO more common method of object creation could be helpful.
Check this out: Use of alloc init instead of new
You could also try removing all the code for adding the Cards to the array. So you'd essentially have:
card = [Card new];
[card release];
This could help you find memory issues associated w/ the array retaining the object perhaps?

Pass a block of code?

Is it possible to pass a block of code, for example:
int i = 0;
while (i < [array count]) {
//Code to pass in here
i++;
}
Reason being that i need to perform various actions on every item in an array at different times, it'd be nice to have 1 method and pass it a block of code to run.
Have you considered using blocks. It's just an idea and not working or compilable code
typedef int (^block_t)();
-(void) methodName:(block_t) code_block
{
int i = 0;
while (i < [array count]) {
code_block() //Code to pass in here
i++;
}
block_t youCode = ^{ NSLog("Just an example"); }
[self methodName:youCode];
You can definitely iterate an array and process a block of code on it. This feature has been a standard part of Objective C since 2.0, iOS since 4.0 and in addition was included in Snow Leopard. If you look up the NSArray class reference you will find the following functions:
enumerateObjectsAtIndexes:options:usingBlock:
Executes a given block using the
objects in the array at the specified
indexes.
enumerateObjectsUsingBlock: Executes a
given block using each object in the
array, starting with the first object
and continuing through the array to
the last object.
enumerateObjectsWithOptions:usingBlock:
Executes a given block using each
object in the array.
You can define the code block to be executed globally in your implementation file, or in place where its needed. You can find some good examples on block programming here: http://thirdcog.eu/pwcblocks/.
It sounds like you want "blocks", which are a feature of Objective-C similar to "lambdas", "anonymous functions" and "closures" in other languages.
See Apple's documentation: Blocks Programming Topics
You should put the code into a method and call the method like so:
-(void)foo{
int i = 0;
while (i < [array count]) {
[self myMethod];
i++;
}
}
-(void)myMethod{
//Code to pass in here
}
You could also store the method as a variable allowing you to change which method is called
SEL methodToCall = #selector(myMethod);
-(void)foo{
int i = 0;
while (i < [array count]){
[self performSelector:methodToCall];
i++;
}
}
-(void)myMethod{
//Code to pass in here
}
first of all you could give a more detailed example.
second you could take a look at Action or Func in case you need a return message (well something equivalent for obj-C if exists)
but again, not understanding what you need to do, it is hard to give you an answer
cause from you Q i could understand as #Trevor did that you need to run a method:
int i = 0;
while (i < [array count]) {
if (i % 2)
EvenMethod(array[i])
else
OddMethod(array[i])
i++;
}
If you can live with 4.0+ compatibility, I highly recommend the use of blocks.
- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block
gives you all you need and you can define your block right where you need it. There are some other variants of this, too. Please refer to the 'NSArray' documentation.
Why not just define functions that do what you want, and call them at various times with the items in your array as arguments?
If your concern is that you don't want redundant code with multiple while loops you have here, you could write a function that takes an array and a function as an argument, then applies that function to every element in the array.
Adapted from here:
//------------------------------------------------------------------------------------
// 2.6 How to Pass a Function Pointer
// <pt2Func> is a pointer to a function which returns void and takes an NSObject*
void DoForAllItems( NSArray* array, void (*pt2Func)(NSObject*) )
{
int i = 0;
while (i < [array count]) {
(*pt2Func)([array objectAtIndex:i]);
i++;
}
}
// 'DoIt' takes an NSObject*
void DoIt (NSObject* object){ NSLog(#"DoIt"); }
// execute example code
void Pass_A_Function_Pointer()
{
NSArray* array= [NSArray arrayWithObjects:#"1", #"2", nil];
DoForAllItems(array, &DoIt);
}
http://thirdcog.eu/pwcblocks/#objcblocks
Blocks were added recently to Objective-C I hope they have found their way to the Iphone also.
and it was anwered here also before:
Using Objective-C Blocks
Regards
If you are using Objective C++, I would strongly recommend function objects (even over blocks). They have a nice syntax, are easy to use, and are supported everywhere on modern C++ compilers (MSVC++11, GNUC++11, and LLVMC++11):
void go( function<void (int arg)> func )
{
int i = 0;
while (i < [array count]) {
//Code to pass in here
func( i ) ; // runs func on i
i++;
}
}
calling it:
go( []( int arg ){ // the square brackets are the "capture"
printf( "arg was %d\n", arg ) ; // arg takes on whatever value was passed to it,
// just like a normal C function
} ) ;

sqlite3_step return code 21 during loadView

Experimenting with sqlite, I want to init a list view with data from the DB. My source looks like this:
-(void) initTheList {
sqlite3 *db;
int rows = 0;
const char* dbFilePathUTF8 = [searchTermDBLocation UTF8String];
int dbrc = sqlite3_open( dbFilePathUTF8, &db );
// count
if (dbrc) {
NSLog( #"Could not open the DB" );
} else {
NSString *queryStatementNS = #"select count(*) from article";
const char* queryStatement = [queryStatementNS UTF8String];
sqlite3_stmt *dbps;
dbrc = sqlite3_prepare_v2(db, queryStatement, -1, &dbps, NULL);
if (sqlite3_step(dbps) == SQLITE_ROW) {
rows = sqlite3_column_int(dbps, 0);
} else {
NSLog(#"SQL step failed code: %d", sqlite3_step(dbps));
NSLog(#"Attempted Query: %#", queryStatementNS);
}
[queryStatementNS release];
}
if (rows > 1000) { ... } else { ... };
...
Actually I thought it would be good to envoke the code only one time once the view is loaded. So I added the initialization of the array and the method call to:
- (void)loadView {
[super loadView];
tableData = [[NSMutableArray alloc] initWithObjects:nil];
[self initTheList];
}
However, doing so, sqlite3_step returns x15 (SQLITE_MISUSE 21 /* Library used incorrectly */). If I place the code to invoke the method in the numberOfRowsInSection method, the call works fine.
Can somebody please give me a hint where I can learn more about the lifecycles and the relation to the sqlite database? It surprises me that I can open the DB but reading fails, while the same code placed in a method that is obviously called at a later point in time works fine.
I just ran into the error code 21 problem myself ("Library used incorrectly.") I couldn't find any helpful answers on the Web, and I was just about ready to conclude that there was some bug in the SQLite3 library in XCode. And then, at long last, I found my problem: a subtle typo in my SQL.
The error was happening during an INSERT OR REPLACE statement. But that particular statement itself had no typo, so I didn't find where I went wrong for the longest time. The database file was being created, so I ran a (Unix) strings command on it, and discovered that I had created a typo in one of the field names during the table's creation. The table created fine, but with the wrong field name. When I was doing the INSERT OR REPLACE, I was using the correct field name. Ah! The mismatch caused the error.
I don't know if this is your problem; but it is very easy to make a typo when creating SQL statements, and they aren't always easy to track down (as I just demonstrated to myself this afternoon). If I were you, I would double check every statement you have.
Hope this helps!
Today I discovered that error 21 is returned by sqlite3_step() if the prepared statement pointer happens to be NULL (zero).

NSString stringWithFormat swizzled to allow missing format numbered args

Based on this SO question asked a few hours ago, I have decided to implement a swizzled method that will allow me to take a formatted NSString as the format arg into stringWithFormat, and have it not break when omitting one of the numbered arg references (%1$#, %2$#)
I have it working, but this is the first copy, and seeing as this method is going to be potentially called hundreds of thousands of times per app run, I need to bounce this off of some experts to see if this method has any red flags, major performance hits, or optimizations
#define NUMARGS(...) (sizeof((int[]){__VA_ARGS__})/sizeof(int))
#implementation NSString (UAFormatOmissions)
+ (id)uaStringWithFormat:(NSString *)format, ... {
if (format != nil) {
va_list args;
va_start(args, format);
// $# is an ordered variable (%1$#, %2$#...)
if ([format rangeOfString:#"$#"].location == NSNotFound) {
//call apples method
NSString *s = [[[NSString alloc] initWithFormat:format arguments:args] autorelease];
va_end(args);
return s;
}
NSMutableArray *newArgs = [NSMutableArray arrayWithCapacity:NUMARGS(args)];
id arg = nil;
int i = 1;
while (arg = va_arg(args, id)) {
NSString *f = [NSString stringWithFormat:#"%%%d\$\#", i];
i++;
if ([format rangeOfString:f].location == NSNotFound) continue;
else [newArgs addObject:arg];
}
va_end(args);
char *newArgList = (char *)malloc(sizeof(id) * [newArgs count]);
[newArgs getObjects:(id *)newArgList];
NSString* result = [[[NSString alloc] initWithFormat:format arguments:newArgList] autorelease];
free(newArgList);
return result;
}
return nil;
}
The basic algorithm is:
search the format string for the %1$#, %2$# variables by searching for %#
if not found, call the normal stringWithFormat and return
else, loop over the args
if the format has a position variable (%i$#) for position i, add the arg to the new arg array
else, don't add the arg
take the new arg array, convert it back into a va_list, and call initWithFormat:arguments: to get the correct string.
The idea is that I would run all [NSString stringWithFormat:] calls through this method instead.
This might seem unnecessary to many, but click on to the referenced SO question (first line) to see examples of why I need to do this.
Ideas? Thoughts? Better implementations? Better Solutions?
Whoa there!
Instead of screwing with a core method that you very probably will introduce subtle bugs into, instead just turn on "Static Analyzer" in your project options, and it will run every build - if you get the arguments wrong it will issue a compiler warning for you.
I appreciate your desire to make the application more robust but I think it very likely that re-writing this method will more likely break your application than save it.
How about defining your own interim method instead of using format specifiers and stringWithFormat:? For example, you could define your own method replaceIndexPoints: to look for ($1) instead of %1$#. You would then format your string and insert translated replacements independently. This method could also take an array of strings, with NSNull or empty strings at the indexes that don't exist in the “untranslated” string.
Your method could look like this (if it were a category method for NSMutableString):
- (void) replaceIndexPointsWithStrings:(NSArray *) replacements
{
// 1. look for largest index in "self".
// 2. loop from the beginning to the largest index, replacing each
// index with corresponding string from replacements array.
}
Here's a few issues that I see with your current implementation (at a glance):
The __VA_ARGS__ thingy explained in the comments.
When you use while (arg = va_arg(args, id)), you are assuming that the arguments are nil terminated (such as for arrayWithObjects:), but with stringWithFormat: this is not a requirement.
I don't think you're required to escape the $ and # in your string format in your arg-loop.
I'm not sure this would work well if uaStringWithFormat: was passed something larger than a pointer (i.e. long long if pointers are 32-bit). This may only be an issue if your translations also require inserting unlocalised numbers of long long magnitude.

How do I free() after malloc() when the result of malloc() is returned by the function?

I have the following instance method (adapted from Listing 3-6 of the Event Handling section in the iPhone Application Programming Guide):
- (CGPoint)originOfTouch:(UITouch *)touch
{
CGPoint *touchOriginPoint = (CGPoint *)CFDictionaryGetValue(touchOriginPoints, touch);
if (touchOriginPoint == NULL)
{
touchOriginPoint = (CGPoint *)malloc(sizeof(CGPoint)); // leaks
CFDictionarySetValue(touchOriginPoints, touch, touchOriginPoint);
*touchOriginPoint = [touch locationInView:touch.view];
}
return *touchOriginPoint;
}
Every once in a while my app leaks 16 Bytes as a result of the call to malloc(). I'm not sure how to return touchOriginPoint while free()ing it as well.
If you do not care a minor performance loss, use an NSMutableDictionary and store the point as an NSValue:
NSValue* touchOriginPointValue = [touchOriginPoints objectForKey:touch];
if (touchOriginPointValue == nil) {
touchOriginPointValue = [NSValue valueWithCGPoint:[touch locationInView:touch.view]];
[touchOriginPoints setObject:touchOriginPointValue forKey:touch];
}
return [touchOriginPointValue CGPointValue];
If you must use the CFDictionary approach, you have to find a place to free those malloc-ed memory when the values are not needed. Therefore, you have to pass the values callbacks when creating the dictionary
static void free_malloced_memory (CFAllocatorRef allocator, const void *value) {
free((void*)value);
}
static const CFDictionaryValueCallBacks values_callbacks = {0, NULL, free_malloced_memory, NULL, NULL};
...
touchOriginPoints = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, & values_callbacks);
...
If you must return the malloc'd value from the function, then you have passed the responsibility for freeing the memory to the calling function, or one of its callers.
Since we can't see the calling functions, we can't diagnose any more.
If you are going to be returning an object that is allocated, then either you need to have the caller free() it, or else you need to be using some kind of garbage collection (so it gets freed automatically).
you don't actually return a pointer, the value is copied to a temp value when it is returned, so you aren't really returning the allocation at all, the problem is that you just aren't freeing it either, you add the allocation to the dictionary and just leave it there?
is there like an EndOfTouch function? where you remove the touch from the dictionary? if there is, call free on your allocation there and you should be fine