In my application i have enabled the ARC. But in my application following lines gives me memory leaks according to instruments. It is in ios 7.0.
-(id)init{
variables = [[NSMutableArray alloc] init]; // Leak
events = [[NSMutableArray alloc] init]; //Leak
return self;
}
Update
But in my app if i do something like below it does not show me any leak. But i can't add items in to the variables.
-(id)init{
variables = [[[NSMutableArray alloc] init] copy]; // No Leak
events = [[[NSMutableArray alloc] init] copy]; //No Leak
return self;
}
--
NSString *utfString =[NSString stringWithUTF8String:(const char *)attr->children->content];//Leak
--
-(NSObject*)createObjectForClass:(NSString*)className{
Class cls = NSClassFromString(className);
NSObject *object = [[cls alloc]init]; //Leak
if(cls != nil){
CFRelease((__bridge CFTypeRef)(cls));
}
return object;
}
Does anyone has any idea how to fix this?
My guess right now is that your entire object is leaking, which means that the NSMutableArrays created in -init also leak. The version that calls copy isn't leaking because the copy is probably returning a singleton instance of NSArray (as there are zero elements in it, and it's an immutable NSArray, there's probably a singleton instance for that).
Related
I have a memory growth issue in my app.
Since
describing the full code here is intimidating,
I narrowed it down to this simple scenario where I switch back and forth between two view controllers to learn basic memory dynamics.
- (void)viewDidLoad {
[super viewDidLoad];
for (int i=0; i<100000; i++)
{
__weak NSString* str = [NSString stringWithFormat:#"abcsdf"];
str = nil;
}
}
This supposed to show no memory growth, because I allocate 'str' and deallocate 'str' by making 'str' becomes nil, thus losing the owner.
But, the memory keeps growing.
Everytime I load this view controller, the memory keeps growing and never coming back.
Can anyone tell me why is that?
I am using ARC.
Your code snippet includes several interesting things about iOS/OS X memory management.
__weak NSString* str = [NSString stringWithFormat:#"abcsdf"];
str = nil;
The code is the same as the following without ARC.
NSString* str = [[[NSString alloc] initWithFormat:#"abcsdf"] autorelease];
str = nil;
Because stringWithFormat: class method does not begin with "alloc", "new", "copy", or "mutableCopy". It's the naming rule. So the NSString object is retained by an Autorelease Pool. The Autorelease Pool might be in the main Runloop. Thus the NSString object was not deallocated immediately. It causes memory growth. #autoreleasepool solves it.
#autoreleasepool {
__weak NSString* str = [NSString stringWithFormat:#"abcsdf"];
str = nil;
}
The NSString object is deallocated at the end of #autoreleasepool code block.
By the way, [NSString stringWithFormat:#"abcsdf"] might not allocate any memory every time. The reason is that it's static string. Let's use this class for further explanation.
#import <Foundation/Foundation.h>
#interface Test : NSObject
+ (instancetype)test;
#end
#implementation Test
- (void)dealloc {
NSLog(#"Test dealloc");
}
+ (instancetype)test
{
return [[Test alloc] init];
}
#end
Here is test code for __weak.
#autoreleasepool {
NSLog(#"BEGIN: a = [Test test]\n");
__weak Test *a = [Test test];
NSLog(#"END: a = [Test test]\n");
a = nil;
NSLog(#"DONE: a = nil\n");
}
The result of the code.
BEGIN: a = [Test test]
END: a = [Test test]
DONE: a = nil
Test dealloc
You said deallocate 'str' by making 'str' becomes nil, thus losing the owner. It is not correct. a weak variable doesn't have ownership of the object. The Autorelease Pool does have the ownership of the object. That's why the object was deallocated at the end of the #autoreleasepool code block. Take a look at the other test code for this case.
NSLog(#"BEGIN: a = [[Test alloc] init]\n");
__weak Test *a = [[Test alloc] init];
NSLog(#"END: a = [[Test alloc] init]\n");
a = nil;
NSLog(#"DONE: a = nil\n");
You can see a compilation warning from the code.
warning: assigning retained object to weak variable; object will be
released after assignment [-Warc-unsafe-retained-assign]
__weak Test *a = [[Test alloc] init];
^ ~~~~~~~~~~~~~~~~~~~
[[Test alloc] init] doesn't register the object to Autorelease Pool. Well, no need #autoreleasepool any more. And a is __weak variable, so the object will not be retained from anything. Thus the result is
BEGIN: a = [[Test alloc] init]
Test dealloc
END: a = [[Test alloc] init]
DONE: a = nil
No ownership no life. The object was deallocated immediately after it was allocated. I think you wanted to write the code without __weak as the following.
NSLog(#"BEGIN: a = [[Test alloc] init]\n");
Test *a = [[Test alloc] init];
NSLog(#"END: a = [[Test alloc] init]\n");
a = nil;
NSLog(#"DONE: a = nil\n");
The result is as expected. The object was released by assigning nil to the strong variable a. Then no one has the ownership of the object, the object was deallocated.
BEGIN: a = [[Test alloc] init]
END: a = [[Test alloc] init]
Test dealloc
DONE: a = nil
This question already has answers here:
NSMutableArray addObject not working
(2 answers)
Cannot add object to an NSMutableArray array
(2 answers)
Closed 10 years ago.
I think, I am doing a pretty basic mistake, but I am using an NSMutableArray and this somehow doesn't add the object, I'm sending it its way. I have a property (and synthesize)
#property (nonatomic, strong) NSMutableArray *kpiStorage;
and then:
ExampleObject *obj1 = [[ExampleObject alloc] init];
[kpiStorage addObject:obj1];
ExampleObject *obj2 = [[ExampleObject alloc] init];
[kpiStorage addObject:obj2];
NSLog(#"kpistorage has:%#", [kpiStorage count]);
and that always returns (null) in the console. What am I misunderstanding?
Make sure you allocated memory for kpiStorage.
self.kpiStorage = [[NSMutableArray alloc] init];
On top of forgetting to allocated memory for your NSMutableArray, your NSLog formatting is also wrong. Your app will crash when you run it. The following changes are needed
You will need to add
self.kpiStorage = [[NSMutableArray alloc] init];
and change your NSLog to the following
NSLog(#"kpistorage has:%d", [self.kpiStorage count]);
If you are not using ARC make sure you should not create a memory leak in your project. So better way would be allocating like this
NSMutableArray *array = [[NSMutableArray alloc] init];
self.kpiStorage = array;
[array release];
make it a habit to do not directly do
self.kpiStorage = [[NSMutableArray alloc] init];
in this case your property's retain count is incremented by 2. For further reading you can stydy Memory Leak when retaining property
I just noticed a surprising behavior of NSArray, that's why I'm posting this question.
I just added a method like:
- (IBAction) crashOrNot
{
NSArray *array = [[NSArray alloc] init];
array = [[NSArray alloc] init];
[array release];
[array release];
}
Theoretically this code will crash. But In my case it never crashed !!!
I changed the NSArray with NSMutableArray but this time the app crashed.
Why this happens, why NSArray not crashing and NSMutableArray crashes ?
In general, when you deallocate an object the memory is not zeroed out, it’s just free to be reclaimed by whoever needs it. Therefore if you keep a pointer to the deallocated object, you can usually still use the object for some time (like you do with your second -release message). Sample code:
#import <Foundation/Foundation.h>
#interface Foo : NSObject
#property(assign) NSUInteger canary;
#end
#implementation Foo
#synthesize canary;
#end
int main(int argc, const char * argv[])
{
#autoreleasepool {
Foo *foo = [[Foo alloc] init];
[foo setCanary:42];
[foo release];
NSLog(#"%li", [foo canary]); // 42, no problem
}
return 0;
}
There are no checks against this by default, the behaviour is simply undefined. If you set the NSZombieEnabled environment value, the messaging code starts checking for deallocated objects and should throw an exception in your case, just as you probably expected:
*** -[Foo canary]: message sent to deallocated instance 0x100108250
By the way, the default, unchecked case is one of the reasons why memory errors are so hard to debug, because the behaviour might be highly non-deterministic (it depends on memory usage patterns). You might get strange errors here and there around the code, while the bug is an over-released object somewhere else. Continuing in the previous example:
Foo *foo = [[Foo alloc] init];
[foo setCanary:42];
[foo release];
Foo *bar = [[Foo alloc] init];
[bar setCanary:11];
NSLog(#"%li", [foo canary]); // 11, magic! (Not guaranteed.)
As for why is NSArray different from NSMutableArray, an empty array looks like a special beast indeed:
NSArray *foo = [[NSArray alloc] init];
NSArray *bar = [[NSArray alloc] init];
NSLog(#"%i", foo == bar); // yes, they point to the same object
So that might have something to do with it. But in general case, working with deallocated objects might do anything. It might work, it might not, it might spill your coffee or start a nuclear war. Don’t do it.
The simplest thing I can think of is that an empty NSArray is some kind of "constant" in the Foundation framework - e.g. an object similar to a NSString literal, which would have a retainCount (if you were to invoke it) of -1, and it could never be -dealloc'd.
I am from android background and I just started working on iPhone
I want to perform this operation in iPhone as I do in Android.
ArrayList<String> aa = new ArrayList<String>();
public void fillArray(String s)
{
aa.add(s);
}
As Binyamin Sharet suggest you have to use NSMutableArray. This class allows you to create a dynamic array. You can perform addition or deletion. On the contrary NSArray is a immutable version of it. You cannot add or delete objects to a NSArray once created.
The same distinction can be applied to NSDictionary and NSMutableDictionary (and other).
Here a simple example.
NSMutableArray* arr = [[NSMutableArray alloc] init];
[arr addObject:#"first string"];
[arr addObject:#"second string"];
An important aspect of NSMutableArray (the same could be applied to other class) is the memory management one. When you add an object to a NSMutableArray it retains objects added to it. So, if you NOT use ARC you have to deal with this aspect.
NSMutableArray* arr = [[NSMutableArray alloc] init];
id obj = [[NSObject alloc] init]; // a general object
[arr addObject:obj];
[obj release];
For further info I suggest you to read about NSMutableArray class reference.
Hope it helps.
There seem to be some memory leaks in the following loop:
NSMutableArray *array1 = [[NSMutableArray alloc] init];
for(SomeClass *someObject in array2){ //has already been populated;
if (someObject.field == desiredValue){
[array1 addObject:someObject];
}
}
//EDIT:
//use array1 for very secret operations
[array1 release];
Any ideas why?
Are you releasing all your retained properties in SomeClass of yours? Make sure in dealloc release all retained properties.. Make sure your SomeClass is leak free..