开发者

YAJL memory leak problem array

开发者 https://www.devze.com 2023-03-03 13:44 出处:网络
I am trying to fetch JSON data every 2 seconds and pass it to another class for processing, everything works fine but the below code seems to have memory leaks 开发者_如何学Go(from Instruments) but I

I am trying to fetch JSON data every 2 seconds and pass it to another class for processing, everything works fine but the below code seems to have memory leaks 开发者_如何学Go(from Instruments) but I cannot figure out what is wrong and how I can fix, can someone please advise ???

* Updated with the full logic and it looks like the array that is passed on to the main method is leaking and Instruments is falsely reporting that as YAJL leak..(not very sure thou)*

    @property (nonatomic,retain,readwrite) NSMutableArray *deviceListArray;


    - (void)viewDidLoad
    {
        [super viewDidLoad];
        deviceListArray=[[NSMutableArray alloc]init];
        [self init];
        TestClass *initiateData = [GetData alloc]init];
        [initiateData startTimer];
        [initiateData release];
    }

    - (id) init{
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(receiveDeviceListNotification:) 
                                                     name:@"devicelist"
                                                   object:nil];
         }

    - (void) receiveDeviceListNotification:(NSNotification *) notification{
            deviceListArray=[notification object];
            [deviceListTable reloadData];

    }

    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

        return [deviceListArray count];
    }

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        [deviceListArray retain]; //CRASHES WITHOUT RETAIN specified here
        static NSString *CellIdentifier = @"Cell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        cell.textLabel.textColor = [UIColor redColor]; 
        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
        }
        [cell.textLabel setText:[deviceListArray objectAtIndex:indexPath.row]]; //CRASHES if i remove the retain on devicelistarray
        return cell;
    }


    @class TestClass;

    @implementation TestClass

    - (void)startTimer:(NSString *)timerstring
    {
        if(timerstring ==@"StartNow")
        {
            NSLog(@"Timer started");
            [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(TestMethod:) userInfo:nil repeats:YES];
        }
        else{
            NSLog(@"string not received");
        }
    }

    -(void)TestMethod:(NSTimer *)Timer {            
        NSTimeInterval timeNow= [NSDate timeIntervalSinceReferenceDate];
        NSData  *JSONData = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://www.example/data.json"]];

        NSArray *testArray=[JSONData yajl_JSON]; //MEMORY LEAK HERE


        if(testArray==nil)
        {
            NSLog(@"Array is nil");
        }
        else
        {
            NSArray *arrayNumberOne=[[testArray valueForKey:@"devicelist"]objectAtIndex:0];
            NSArray *arrayNumberTwo=[testArray valueForKey:@"arrayNumberTwo"];
            NSArray *arrayNumberThree=[testArray valueForKey:@"arrayNumberThree"];        
            float dowloadY=[[arrayNumberTwo objectAtIndex:0]floatValue];
            float uploadY=[[arrayNumberThree objectAtIndex:0]floatValue];

            NSDictionary  *newarrayNumberTwoData=  [NSDictionary dictionaryWithObjectsAndKeys:
                [NSDecimalNumber numberWithInt:timeNow], [NSNumber numberWithInt:0], 
                [NSDecimalNumber numberWithFloat:dowloadY], [NSNumber numberWithInt:1],nil
            ] ;

            NSDictionary  *newarrayNumberThreeData=  [NSDictionary dictionaryWithObjectsAndKeys:
                [NSDecimalNumber numberWithInt:timeNow], [NSNumber numberWithInt:0],
                [NSDecimalNumber numberWithFloat:uploadY], [NSNumber numberWithInt:1],nil
            ] ;

            [[NSNotificationCenter defaultCenter] postNotificationName:@"devicelist" object:arrayNumberOne];

            [[NSNotificationCenter defaultCenter] postNotificationName:@"TestData2" object:newarrayNumberTwoData];
            [[NSNotificationCenter defaultCenter] postNotificationName:@"TestData3" object:newarrayNumberThreeData];
        }
    }

    -(void) dealloc{
        [super dealloc];
    }

    @end

Memory leak log from Instruments is below

    Leaked Object   #   Address Size    Responsible Library Responsible Frame
    __NSArrayM,569  < multiple >  17.78 KB    MYTESTAPP3  -[YAJLDocument parserDidStartArray:]
    Malloc 80 Bytes,480 < multiple >  37.50 KB    MYTESTAPP3  -[YAJLDocument parserDidStartArray:]
    NSCFString,397  < multiple >  11.44 KB    Foundation  -[NSPlaceholderString initWithBytes:length:encoding:]
    NSCFString,     0x4c1dac0   32 Bytes    Foundation  -[NSPlaceholderString initWithBytes:length:encoding:]


Well, it looks simple. First, you defined your JSONData as 'retain' instead of 'assign', and then upon calling the TestMethod in subsequent runs, you leak the prior one, as you are not using the setter, but rather accessing the instance variable directly. If you don't need the JSONData in any other place, but this method, just define it as a local variable, and don't do anything special - it's autoreleased. And second - the same thing happens to the testArray. Again, if you don't need it in other places, then define as local variable, and if you do, then use the setter.

Update: Now you have a similar problem, just with deviceListArray this time. First, initialize it like this:

self.deviceListArray=[NSMutableArray array];

then, every time you want to assign, use this:

self.deviceListArray = newObject;

in the dealloc do

[deviceListArray release];

0

精彩评论

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