开发者

Memory efficient collection class

开发者 https://www.devze.com 2023-01-02 00:09 出处:网络
I\'m building an array of dictionaries (called keys) in my iphone application to hold the section names and row counts for a tableview.

I'm building an array of dictionaries (called keys) in my iphone application to hold the section names and row counts for a tableview.

the code looks like this:

[self.results removeAllObjects];
[self.keys removeAllObjects];

NSUInteger i,j = 0;
NSString *key = [NSString string];
NSString *prevKey = [NSString string];

if ([self.allResults count] > 0)
{
    prevKey = [NSString stringWithString:[[[self.allResults objectAtIndex:0] valueForKey:@"name"] substringToIndex:1]];

    for (NSDictionary *theDict in self.allResults)
    {
        key = [NSString stringWithString:[[theDict valueForKey:@"name"] substringToIndex:1]];

        if (![key isEqualToString:prevKey])
        {
            NSDictionary *newDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                           [NSNumber numberWithInt:i],@"count",
                                           prevKey,@"section",
                                           [NSNumber numberWithInt:j],
                                           @"total",nil];

            [self.keys addObject:newDictionary];
            prevKey = [NSString stringWithString:key];
            i = 1;
        }
        else
        {
            i++;
        }
        j++;

    }

    NSDictiona开发者_如何转开发ry *newDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                   [NSNumber numberWithInt:i],@"count",
                                   prevKey,@"section",
                                   [NSNumber numberWithInt:j],
                                   @"total",nil];

    [self.keys addObject:newDictionary];

}

[self.tableview reloadData];

The code works fine first time through but I sometimes have to rebuild the entire table so I redo this code which orks fine on the simulator, but on my device the program bombs when I execute the reloadData line :

malloc: *** mmap(size=3772944384) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
malloc: *** mmap(size=3772944384) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
Program received signal:  “EXC_BAD_ACCESS”.

If I remove the reloadData line the code works on the device.

I'm wondering if this is something to do with the way I've built the keys array (ie using autoreleased strings and dictionaries).


The error message is giving you a very clear reason why the allocation failed:

malloc: *** mmap(size=3772944384) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
malloc: *** mmap(size=3772944384) failed (error code=12)
*** error: can't allocate region

Specifically, the size is 3,772,944,384; almost 4GB. I.e. you are asking malloc() to allocate something that is causing malloc to think it needs to memory map (mmap) nearly 4GBs of address space!

Now, if your input strings are really darned huge, then your code will be bloating the autorelease pools as davydotcom says, but they'd have to be really really huge to cause that to happen. And if it is that huge, then are you ending up with 10s of thousands or hundreds of thousands of rows in your table? If so, don't do that -- it is too hard for the user to work with.

As the error says, set a breakpoint on malloc_error and post a backtrace.

Note that this:

NSString *key = [NSString string];
NSString *prevKey = [NSString string];

Is nonsense.

OK -- a second glance of your code indicates that a review of the Objective-C guide and the Cocoa memory management guide would be useful.

In the first four lines of code, you both leak the previous and over-retain the new self.keys and self. self.results (assuming both are retain properties, as they should be).

Try, also, to use Build & Analyze on your code.


If at all possible i would highly recommend not using autoreleased strings and objects in general as they also decrease performance. Everything in your code set looks correct except for the odd statement up top.

the first 2 lines remove all the objects from the arrays then you assign pointers to new self.keys and self.results

assign the self.keys and self.results only once and when reloading data simply call removeAllObjects.


An array of dictionaries called keys… [self.keys addObject:newDictionary].. needs.. lie.. down.

0

精彩评论

暂无评论...
验证码 换一张
取 消