-1

I have the one Class "TestA" and puts its object in NSMutable dictionary in main function. And second class with name "ThreadClass" having a thread. IN this thread i get the object from dictionary and used it.When i run this program the Instrument shows me a memory leak in this thread. But i don't understand why memory is leak because i did not used any new or alloc, copy or retain. I attached complete code of my program with main class. Need a qucik help about memory management.

I also have a question that if i have a class having NSString as data member. If i put the objects of this in NSMutabledictionary then how i handle the memory management for this. thanx

#import <Cocoa/Cocoa.h>

@interface TestA : NSObject {

@public

    NSString *strTemp1;
}
@end

#import "TestA.h"

/////////////////////////////////////////////
//Implementation class

@implementation TestA

-(id)init
{
self = [super init];

if (self != nil) 
{       
    //strTemp1 = [[NSString alloc] init];
    //printf("\n Temp 1 %d \n", [strTemp1 retainCount]);
}
return self;
}
@end

//Thread Class

#import <Cocoa/Cocoa.h>

#import "TestA.h"
@interface ThreadClass : NSObject {

}
@end


#import "ThreadClass.h"

extern NSMutableDictionary *clData;

@implementation ThreadClass

-(void)Initialize
{
[NSThread detachNewThreadSelector:@selector(AnimateThread:) toTarget:self  withObject:nil];
printf("\n<<<<<<<<<<<<<<< Start Animator Thread Called >>>>>>>>>>>>>>>>>>>>>\n");
}

//==========================================================================
- (void) AnimateThread:(id) inObject
{
    NSAutoreleasePool *Pool = [[NSAutoreleasePool alloc] init];

NSDate *timeToSleep = [NSDate dateWithTimeIntervalSinceNow:(NSTimeInterval)5];

while (1) 
{
    //NSAutoreleasePool *threadPool = [[NSAutoreleasePool alloc] init];

    printf("\n Collection Size:%d \n", [clData count]);
    TestA *obj1 = [clData objectForKey:@"abc"];

    printf("\nThread Memory Counter:%d \n", [obj1 retainCount]);
    printf("\nThread Memory Counter:%s \n", [obj1->strTemp1 UTF8String]);

    //Sleep Thread for 5 Seconds
    [timeToSleep release];
    timeToSleep = [NSDate dateWithTimeIntervalSinceNow:(NSTimeInterval)5];
    [NSThread sleepUntilDate:(NSDate *)timeToSleep];
    //[timeToSleep release];

    //[threadPool release];
}

[Pool release];
}   
@end


//////////////////////////
Main Class


#import <Cocoa/Cocoa.h>
#import "TestA.h"
#import "ThreadClass.h"

NSMutableDictionary *clData = nil;
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];


clData = [[NSMutableDictionary alloc] init];

//Creating Thread Class
ThreadClass *obj = [ThreadClass new];
[obj Initialize];
[obj release];

TestA *obj1 = [[TestA alloc] init];
NSString *strKey =[NSString new];
strKey = @"abc";

printf("\n Memory Counter:%d \n", [obj1 retainCount]);
printf("\n Memory Counter:%d \n", [obj1->strTemp1 retainCount]);

NSString *strTemp = @"Test Program";
obj1->strTemp1 = [NSString stringWithFormat:@"%s", [strTemp UTF8String]];
[obj1->strTemp1 retain];

printf("\n Memory Counter:%s \n", [obj1->strTemp1 UTF8String]);

[clData setObject:obj1 forKey:strKey];

printf("\nAfter Memory Counter:%d \n", [obj1 retainCount]);
printf("\nAfter Memory Counter:%d \n", [obj1->strTemp1 retainCount]);


[strKey release];
[obj1 release];

[pool release];

return NSApplicationMain(argc,  (const char **) argv);
}
bbum
  • 161,681
  • 23
  • 270
  • 358
majid khan
  • 11
  • 2
  • 1
    Easiest way is to use ARC. See: http://stackoverflow.com/questions/6385212/how-does-the-new-automatic-reference-counting-mechanism-work – tillerstarr Nov 12 '12 at 13:07
  • thanx for your reply. But here i did not create my own object in collection. This is autorelease object. In main i used [obj1->strTemp1 retain]; before adding the object in collection i increased its reference count to 1. If i did not do this step then program is crashed in thread loop. I did not understand why this is happend. – majid khan Nov 12 '12 at 13:37
  • You probably need to read on memory management in general as well as properties. Try this: https://developer.apple.com/library/mac/#documentation/General/Conceptual/DevPedia-CocoaCore/MemoryManagement.html – NikosM Nov 12 '12 at 13:37
  • I already read the apple documentation about memory management. Can you point out flaws why memory is leak in above code. I need the reason or solution of above code for memory leaks. thanx – majid khan Nov 12 '12 at 14:33

2 Answers2

2

There is a ton of stuff wrong with that code. Well beyond memory management.

I would suggest starting with the Objective-C language guide, then moving on to the iOS application architecture guide or the Cocoa guide for OS X applications.

A quick list of some of what is wrong:

• In general, you shouldn't use threads directly and any thread should never use a while(1) {...sleep(..);...} polling construct. Run loops, queues, and GCD should be used instead.

retainCount is utterly useless. Don't call it. See http://www.whentouseretaincount.com for details.

• Do not access instance variables via ->. Both breaks encapsulation and not at all a pattern used in Objective-C outside of very rare circumstances (copying objects, sometimes).

• This pattern doesn't make sense: NSString *strKey =[NSString new]; strKey = @"abc";. It leaks an instance of an empty NSString (or would, anyway, if it weren't for an optimization in the Foundation). There is no need to do that first assignment.

• Structuring an app with a bunch of code in main() that then passes control to Cocoa doesn't make sense. Either write a Foundation based command line tool or a proper Cocoa app.

• Method names begin with lowercase letters and are camelCased.

• It looks like you might be going down the path of doing some animation in a Cocoa application? If so, you'll want to read up on Core Animation.

• If this is a new project, use ARC.

bbum
  • 161,681
  • 23
  • 270
  • 358
0

Use a property. In the header:

@interface TestA : NSObject
{
   NSString *strTemp1_;
}
@property (nonatomic, copy) NSString* strTemp1;
@end

In the implementation:

@synthesize strTemp1=strTemp1_;

-(id)init
{
    self = [super init];

    if (self != nil) 
    {     
        strTemp1_=@"MyString";
    }
    return self;
}

//since your not using ARC you need to make sure that the property is NIL'd so that it will be released properly.
- (void) dealloc
{
    self.strTemp1=NULL;
}
tillerstarr
  • 2,576
  • 1
  • 19
  • 35