Memory Leaks with ARC? - objective-c

I am new to Objective C, and I've read several documents both here on Stack Overflow and on Apple's web site about Automatic Reference Counting, but I still can't figure out why "Leaks" is telling me my code is leaking memory. It's probably important to note that all of this code is running on a background thread which is initiated by an NSOperationQueue.
For example, I have something like this:
NSArray *times = <receives an array of NSStrings>;
NSArray *codes = <receives an array of NSStrings>;
// these two arrays are == in length
NSMutableArray *fingerprint = [NSMutableArray array];
for (int x = 0; x < [times count]; x++) {
long numToAdd = strtol([[codes objectAtIndex:x] cStringUsingEncoding:NSUTF8Encoding], NULL, 16);
[fingerprint addObject:[NSNumber numberWithLong:numToAdd]];
numToAdd = strtol([[times objectAtIndex:x] cStringUsingEncoding:NSUTF8Encoding], NULL, 16);
[fingerprint addObject:[NSNumber numberWithLong:numToAdd]];
}
Leaks claims there is a leak on the line the allocates the array, as well as a leak on the first object add, but not the second. I have no idea why these leaks exist. Any help is appreciated.
If more code is needed, please comment and I'll be happy to provide.

Related

dispatch_apply gives incorrect output data

I have two arrays: array1 and array2. Each object of arrays is an array too (2D arrays). In this way I multiple them. So how I have big arrays I use dispatch_apply. Every time i receive different results include a right result. Maybe somebody knows how to fix it?
dispatch_apply([array2 count], queue, ^(size_t j)
{
k = 0;
for (int l = 0; l < [[array1 objectAtIndex:0] count]; l++) {
k += [[[array1 objectAtIndex:i] objectAtIndex:l] intValue] *
[[[array2 objectAtIndex:j] objectAtIndex:l] intValue];
}
kNSNumber = [NSNumber numberWithInt:k];
[multipliedArrayInto replaceObjectAtIndex:j withObject:kNSNumber];
});
[resulArray insertObject:multipliedArrayInto atIndex:i];
}
There's two things, I can suggest, and I bet one of them (or both) is the overarching solution to your problem.
First, I would declare k local to the block, so there would be no question that you are overwriting it or not. You likely have the same problem with kNSNumber inside the block. If you are just using that NSNumber instance to slam into the multipliedArrayInto accumulator, you may as well remove kNSNumber, and use #(k) in it's place (if only to be more readable). Similarly, make sure multipliedArrayInto is declared just before the dispatch_apply, in what looks like an outer for loop (where ever i is coming from). And finally, make sure resulArray is instantiated, or otherwise readied just before that outer for loop.
Second, is queue a concurrent or serial queue? If you are using dispatch_apply like a parallel-executing for/enumeration -- which is likely, I think, so you are taking about handling "big arrays" efficiently -- then you are practically guaranteeing that k is being overwritten. If you change it to serial, it may work as designed. If you want it to be parallel, you will need to move the declaration of your k accumulator inside the block, and make sure the declaration of other variables makes sense, too.
Update to reflect question updates:
#antonytonies ideally, your followup answer on this thread should be moved into the question itself, so that people can follow this thread easier.
So, it looks like what I described is exactly your problem.
The global queues are all concurrent queues, which means that (hypothetically) all the dispatch blocks are executing at once, and the contents of k and other variables are getting blown away depending on how the order of the blocks executes.
I've taken your update (in the "answer" you added), and modified it to probably work:
// I renamed your method, because nameless parameters pain me. This is cosmetic, and doesn't
// matter for the problem at hand.
- (NSMutableArray *)multiplicationArrays:(NSMutableArray *)array vector:(NSMutableArray *)vector
{
// IMHO, you want to set resultArray to nil here. Another option is to set it to nil in the
// else case, below. Properties in Objective-C are initalized to nil,0,false,etc; you can
// rely on ARC to initialize pointer to objc objects on the stack, too. However, someone
// reading this code may or may not know that. IMHO, using the explicitly assignement makes it
// clear that you're going to be returning `nil` or an instance of `NSMutableArray`.
NSMutableArray *resultArray = nil;
if ([[array objectAtIndex:0] count] == [vector count]) {
// Nicely done w/ pre-allocating the result array here, so that there's no question
// of the indexes matches the results later on.
resultArray = [[NSMutableArray alloc] initWithCapacity:[array count]];
for (int i=0; i < [array count]; i++) {
[resultArray insertObject:[NSNull null] atIndex:i];
}
// 'queue' here is a concurrent queue. This means that you are proclaiming to the runtime
// that the blocks being executed are able to operate correctly w/o interference from each
// other. This is also thought of in terms of parallel execution: all these blocks may run
// **at once**. This *also* means, that you must not share storage between them.
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply([array count], queue, ^(size_t j) {
// Moved 'result' inside the block.
NSInteger result = 0;
for (int l = 0; l < [[array objectAtIndex:0] count]; l++) {
// These array reads are **NOT** thread safe. They probably don't cause must trouble in
// practice, but you may want to reconfigure this.
result += [[[array objectAtIndex:j] objectAtIndex:l] intValue] * [[vector objectAtIndex:l] intValue];
}
// The replace of the object into resultArray is **NOT** thread-safe.
// This probably hasn't caused you much trouble, since you can guarantee that
// you aren't writing at the same index. However, I would strongly suggest to
// change this to be thread-safe.
[resultArray replaceObjectAtIndex:j withObject:#(result)];
});
}
else {
NSLog(#"matrix count isn't correspond");
}
return resultArray;
}
Finally: consider just using Apple's Accelerate framework for this sort of problem solving. It's available on OSX and iOS, so you should have all of your bases covered.
it's the same thing if I multiple 2D-array and vector
-(NSMutableArray*)multiplicationArraysWithVector:(NSMutableArray *)array :(NSMutableArray *)vector
{
NSMutableArray* resultArray;
if ([[array objectAtIndex:0] count] == [vector count])
{
resultArray = [[NSMutableArray alloc] initWithCapacity:[array count]];
for (int i=0; i < [array count]; i++) {
[resultArray insertObject:[NSNull null] atIndex:i];
}
__block NSInteger result;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply([array count], queue, ^(size_t j)
{
result = 0;
for (int l = 0; l < [[array objectAtIndex:0] count]; l++) {
result += [[[array objectAtIndex:j] objectAtIndex:l] intValue] * [[vector objectAtIndex:l]intValue];
}
[resultArray replaceObjectAtIndex:j withObject:#(result)];
});
}
else
{
NSLog(#"matrix count isn't correspond");
}
return resultArray;
}
In this case I can get a right or wrong data result.

Why do we have [NSString string] when we can write [NSString new]?

Obviously I'm not just referring to NSString; there is [NSDictionary dictionary], [NSArray array], and so on. But why have all these methods when we can just send [NSDictionary new], [NSArray new], etc.?
The reason is primarily historical, because the distinction between the two is the reference count of the created object; caring about the reference count has been almost completely obviated by Automatic Reference Counting.
+string and methods like it return objects that are not owned by the caller (they are in an autorelease pool). +new, on the other hand, is one of the "four NARCs", and it does create owning references.
Previous to ARC, you would choose the one that had the memory management implications you needed in particular situation. Now, you can use whichever you prefer. There is no difference at the level of your code.
In some looping cases you may find it preferable to use +new because this still does apparently shorten the lifetime of the object as compared to +string.
To add upon Josh's good answer, when using ARC, using alloc] init] or new is preferred, because you lose the need for #autoreleasepool { ... } to relieve autorelease pressure.
Consider the following code:
for(int i = 0; i < X; i++)
{
//#autoreleasepool {
NSMutableArray* array = [NSMutableArray array];
for(int j = 0; j < Y; j++)
{
[array addObject:[NSString stringWithFormat:#"%d", j]];
}
///Do something with array.
//}
}
As X and Y grow, you will find the memory growing, and would need #autoreleasepool because the objects would only be released when the autorelease pool is drained.
Now consider
for(int i = 0; i < X; i++)
{
NSMutableArray* array = [NSMutableArray new];
for(int j = 0; j < Y; j++)
{
[array addObject:[[NSString alloc] initWithFormat:#"%d", j]];
}
///Do something with array.
}
Here the objects are released once they go out of scope and are no longer retained.
Methods like [NSDictionary dictionary], [NSArray array] and so on, return autoreleased object. Meaning that you don't have the ownership of those objects, and you don't need to worry about memory management.
When you use new or alloc you need to release those objects once you have finished using them.
This distinction is important when you're not using ARC.

NSArray not deallocating in ARC Objective-C

I am trying to write a command line application in Objective-C for a university project. The project needs matrix manipulation so I have written a class to handle all the matrix methods (Addition and multiplication and such). My matrix methods look like this:
- (NSArray *)sumMatrices:(NSArray *)matrices
{
NSMutableArray *sum = [[NSMutableArray alloc] init];
NSInteger cols = [matrices[0][0] count];
NSInteger rows = [matrices[0] count];
for (int i = 0; i < rows; i++) {
NSMutableArray *row = [[NSMutableArray alloc] init];
for (int j = 0; j < cols; j++) {
CGFloat value = 0.0;
for (NSArray *array in matrices) {
value += [array[i][j] doubleValue];
}
[row addObject:[NSNumber numberWithDouble:value]];
}
[sum addObject:[row copy]];
row = nil;
}
return [sum copy];
}
However theres is a massive problem with this programme, I having used objective-c for iOS expect ARC to handle all my memory allocation and deallocation without a problem, however in this case the NSMutableArray 'sum' is never being deallocated, and because this method is being called in a loop which runs 10's of thousands of times (Modelling a double pendulum using RK4) the memory usage builds up and makes the program extremely slow.
Is there any reason this NSMutableArray isn't being deallocated once this method has returned?
Your problem is less about this code and more about the code surrounding it. Let's assume for a moment that your code around it looks like this:
NSArray *matricies; //Declared somewhere else;
NSMutableArray *results = [[NSMutableArray alloc] init];
for (int i=0; i < [matricies count] - 1; i++) {
for (int j=i+1; j < [matricies count]; i++) {
NSArray *sum = [self sumMatrices:#[matricies[i], matricies[j]]];
[results addObject:sum];
}
}
The actual operations that I'm performing are not particularly relevant to this example. The code pattern is. You'll notice I'm using a nested "tight" loop. Control never returns to the run loop until AFTER all calculations are complete. Without ARC, your memory would be freed as soon as the last release was performed, excluding autoreleased objects. With ARC, your memory is not freed until control is returned to the runloop, much the same way autoreleased objects used to. As a result, your code will appear to leak, until processing is complete and the system decides it should release your memory. If the CPU is perpetually under a heavy load, it may not clean up memory until it absolutely has to.
There are a few cleaver ways to use #autoreleasepool to help in this case, but that will make your code significantly slower. Additionally, Objective C is a fairly slow language for objects and method calls. If you are using this code heavily, you should convert it into C or C++ and manage the memory yourself.
without going into much detail you can try to use autoreleasepool
https://developer.apple.com/library/mac/documentation/cocoa/conceptual/memorymgmt/articles/mmAutoreleasePools.html
i would use copy if i want to preserve an array which gets modified but in your case do you really need it ?

How can I manage memory in a loop under ARC without #autoreleasepool block

As before, we usually do something for loop like this:
for (int i = 0 ; i < 5; i ++) {
NSNumber * number = [[NSNumber alloc] initWithInt:i];
[muArray addObject:number];
[number release];
}
But under ARC, there is no release. Can I manage memory without an #autorelease block, like this (directly remove release statement):
for (int i = 0 ; i < 5; i ++) {
NSNumber * number = [[NSNumber alloc] initWithInt:i];
[muArray addObject:number];
}
Similarly, is the #autoreleasepool necessary, like this?
for (int i = 0 ; i < 5; i ++) {
#autoreleasepool{
NSNumber * number = [NSNumber numberWithInt:i];
[muArray addObject:number];
}
}
Your second code block (compiled with ARC), has exactly the same semantics as your first code block (compiled with MRC).
Under ARC, when you set a strong object reference to nil, or when a strong object reference is destroyed, ARC takes care of sending the release message for you. In both examples, the number variable is destroyed at the end of the loop body, so (in the second example) ARC releases the objected that number referenced.
In your third example, the #autoreleasepool will cause the returned NSNumber to be released on each pass through the loop. This might be necessary for a large number of loop iterations. For just five iterations, each creating a single NSNumber, it's not necessary.
Yes, ARC will translate your second example into the first.
You can read more here (apple docs) and here (dr. dobbs).
The autorelease pool example is should also be equivalent, llvm docs

iOS memory leak by dictionary

I am new to iOS programming and I have developed an application for my client. When I run the application using Instruments, however, there appears to be a memory leak problem caused by a dictionary, but if I release it, then the app crashes. I am not sure what the problem is.
This is image of Instruments: http://www.flickr.com/photos/71234685#N02/6791493522/in/photostream/
-(void) generateLiquidProductData:(NSArray*) liquidProduct {
int _count = 52;
self.liquidProductData = [[NSMutableArray alloc] initWithCapacity:_count];
for (int i = 0; i < _count; i++){
float x = i;
float y;
if ((liquidProduct != (id)[NSNull null]) && (liquidProduct != nil) && ([liquidProduct count] != 0)) {
y = [[liquidProduct objectAtIndex:i] floatValue];
y = round(y * 10000.0f) / 10000.0f;
}
else {
y = 0.0;
y = round(y * 10000.0f) / 10000.0f;
}
NSDictionary* _gotLiquidProduct = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithDouble:x],X_VAL,
[NSNumber numberWithDouble:y],Y_VAL,
nil];
NSLog(#"This is y %.5f", y);
[self.liquidProductData addObject:_gotLiquidProduct];
}
}
The memory leak is due to this line:
self.liquidProductData = [[NSMutableArray alloc] initWithCapacity:_count];
Most likely, the property is either marked as retain or copy (usually the former). The correct way to use it would be:
self.liquidProductData = [NSMutableArray arrayWithCapacity:_count];
The leak is because alloc returns an owning reference that you later need to release, but you do not release it. You now assign it to the property which retains the instance. The "relative retain count" is now +2. If you assign a new value to this property, the old instance will get released, but this only makes the "relative retain count" drop to +1, thus the instance never gets deallocated. This in turn will also leak your dictionary and its values, since they are still retained by the leaked array.
Every time you use a method were there is init in the beginning of the name, the object who is returned never get autoreleased so it is your responsibility to release it.
Methods which start by the 'type' like "arrayWith" "stringWith" return objects who are autoreleased.
An other thing, you can use Static analysis to find this kind of leaks, it's really easy.
Xcode static analysis