0

my program works fine but the memory occupation is expending rapidly, i've debug for a long time and found such a problem:

if (some_condition)
{
    NSMutableArray *fftArray256 = [NSMutableArray array];
    NSMutableArray *fftArray = [NSMutableArray array];

    [ESUtils changeToFFTData:pDatas outData:fftArray];//some data will be inserted in the fftArray.
    for(NSNumber *n in fftArray)
    {
        double d = [n doubleValue];
        d *= 256;//change the scale
        [fftArray256 addObject:[NSNumber numberWithDouble:d]];
    }
    fftObj.degree = [self getDegree:fftArray256];

    [fftArray256 removeAllObjects];
    [fftArray removeAllObjects];
}

if i replace

    [fftArray256 addObject:[NSNumber numberWithDouble:d]];

with

    [fftArray256 addObject:@"1"];

everything will be fine, memory will grow before the last two lines, but after that all memory will be released.

if not changing like above the memory occupation will grow after leaving this block, it will repeat endlessly till the program fails. the removeAllObjects method could release part memory but remains a major part in memory, even after leaving this block.

so what's the problem with the [NSNumber numberWithDouble:d]? how can i release them totally before i leave this block?

i know it's not making sense, or I won't ask...

Ethansong
  • 53
  • 6

2 Answers2

1

@"1" - is literal string, as i know it always the same instance

[NSNumber numberWithDouble:d] - it will create always new instance

To release memory try to wrap you code in autoreleasepool

@autoreleasepool {
    NSMutableArray *fftArray256 = [NSMutableArray array];
    ....
    [fftArray removeAllObjects];
}
Alex
  • 1,603
  • 1
  • 16
  • 11
  • i knew autoreleasepool but didn't try it.. and it proved to be useful. the memory occupation droped from crash (over 600MB) to 24MB. – Ethansong Aug 25 '16 at 02:10
0

I searched the related solution according to your question.They said

[fftArray256 addObject:@"1"] takes much memory than [NSNumber numberWithDouble:d] because double is 8 byte.Generally pointers are 8 bytes(64-bit) in iOS.Objects are allocated on the heap; at the lowest level, heap allocation is done by malloc.NSNumber containing an double "they said it has 8 bytes for your pointer, plus 24 bytes for the object (consisting of a 8-byte class pointer and - a 8 byte double, plus 8 bytes of wasted space).

A string literal @"1" will point to a statically allocated string literal object, a string created at runtime will probably have a different representation.In general "8 bytes (pointer on 64-bit)) + 16 bytes (the NSString object) + number of characters * 2 (sizeof(unichar)) rounded up to multiples of 16.

According to above points it seems NSNumber memory(24 bytes) is less than the String literal:@"1"(above 56).

I got above useful details from wolfgang's answer

So If you are using or having ARC,you don't need to release the NSNumber.Automatically it uses and release the object.

But still we need to use autoreleasepool.Sometimes ARC doesn't get rid of retains, releases and autoreleases, it just adds in the required ones for you. So there are still calls to retain, there are still calls to release, there are still calls to autorelease and there are still auto release pools.

So your code should be below like this

 if (some_condition)
 {
  NSMutableArray *fftArray256 = [NSMutableArray array];
  NSMutableArray *fftArray = [NSMutableArray array];

  [ESUtils changeToFFTData:pDatas outData:fftArray];//some data will be inserted in the fftArray.
  for(NSNumber *n in fftArray)
  {
     @autoreleasepool
     {
       double d = [n doubleValue];
       d *= 256;//change the scale
       [fftArray256 addObject:[NSNumber numberWithDouble:d]];
     }
  }
  fftObj.degree = [self getDegree:fftArray256];

  [fftArray256 removeAllObjects];
  [fftArray removeAllObjects];
 }

At the end of the autorelease pool block, objects that received an autorelease message within the block are sent a release message—an object receives a release message for each time it was sent an autorelease message within the block.

Best Example

Community
  • 1
  • 1
user3182143
  • 9,459
  • 3
  • 32
  • 39
  • That quoted answer is very outdated. Most iOS are 64bit architectures now, therefore a point will take 8 bytes. – Sulthan Aug 24 '16 at 16:16
  • Go through all the details inside brother.I mentioned only 8 bytes brother.Don't down vote before read the answer brother. – user3182143 Aug 24 '16 at 16:24
  • "Generally pointers are 4 bytes in iOS" That's not true any more. – Sulthan Aug 24 '16 at 16:47
  • See https://developer.apple.com/library/ios/documentation/General/Conceptual/CocoaTouch64BitGuide/Major64-BitChanges/Major64-BitChanges.html Most (not all) iOS devices are now 64 bit. Of course, there are still some 32bit devices which have 4B pointers but most devices have 8B. – Sulthan Aug 24 '16 at 17:57
  • Mow I updated my answer brother.Thank you brother sulthan.Check it brother. – user3182143 Aug 25 '16 at 16:33