2014-01-21 111 views
0

我正在处理音乐流媒体应用程序。我目前正在接收大量内存泄漏的迹象。仪器说它与下面的代码有关。在while循环期间分配了一些内存块。我打开了ARC。我已经用尽了所有选项并需要一些更多的想法巨大的内存泄漏NSData

NSData * ringBufferReadData = [NSData dataWithBytes:readPointer length:allBytesAvailable]; 
// NSLog(@"READER: THESE ARE THE BYTES WE ARE ABOUT TO READ FROM RING BUFFER %lu ",allBytesAvailable); 

[ringBuffer didReadLength:allBytesAvailable]; 

UInt32 ringBufferReadDataOffset = 0; 

while (ringBufferReadDataOffset < allBytesAvailable) { 

    int packetBytesFilled = [[ringBufferReadData subdataWithRange:NSMakeRange(12 + ringBufferReadDataOffset, 4)] pm_int32AtOffset:0]; 

    int packetDescriptionsBytesFilled = [[ringBufferReadData subdataWithRange:NSMakeRange(16 + ringBufferReadDataOffset, 4)] pm_int32AtOffset:0]; 

    int offset = AUDIO_BUFFER_PACKET_HEADER_SIZE + ringBufferReadDataOffset; 
    NSData* audioBufferData = [NSData dataWithBytes:(char *)([ringBufferReadData bytes] + offset) length:packetBytesFilled]; 

    offset += packetBytesFilled ; 
    NSData *packetDescriptionsData = [NSData dataWithBytes:(char *)([ringBufferReadData bytes] + offset) length:packetDescriptionsBytesFilled]; 

    UInt32 inNumberPackets = packetDescriptionsBytesFilled/AUDIO_STREAM_PACK_DESC_SIZE; 
    AudioStreamPacketDescription *inPacketDescriptions; 

    inPacketDescriptions = [self populatePacketDescriptionArray:packetDescriptionsData 
             packetDescriptionNumber:inNumberPackets]; 

    if (inPacketDescriptions[0].mDataByteSize > 65536) 
    { 
     NSLog(@"packet description size is abnormally large.. soething is wrong"); 
    } 

    [self handleAudioPackets:[audioBufferData bytes] 
       numberBytes:packetBytesFilled 
       numberPackets:inNumberPackets 
      packetDescriptions:inPacketDescriptions]; 

    ringBufferReadDataOffset += AUDIO_BUFFER_PACKET_HEADER_SIZE + packetBytesFilled + packetDescriptionsBytesFilled; 

    free(inPacketDescriptions); 
} 
+0

你用静态分析器了解它吗?点击并按住“运行”,然后选择“分析”。这应该能够拾取发生泄漏的地方。 – Fogmeister

+0

另外,while循环的结尾在哪里? – Fogmeister

+0

while循环开始5行,结束代码中断 – user3218184

回答

1

您在该循环中创建了大量的临时对象;如果它们中的一些最终在自动释放池中而不是明确地为-released,则它们将积累,因为在循环中没有@autoreleasepool。严格来说,这不是严格意义上的内存泄漏(因为它最终会被释放),但它可能看起来像是一种仪器。

尝试重写你的循环,删除一些不必要的NSData对象。例如: -

[ringBuffer didReadLength:allBytesAvailable]; 

const uint8_t *ptr = readPointer; 
const uint8_t *end = ptr + allBytesAvailable; 

while (end - ptr >= AUDIO_BUFFER_PACKET_HEADER_SIZE) { 
    // Might be better if you had a struct type; also, you may need to byte swap? 
    uint32_t packetBytesFilled = *(uint32_t *)(ptr + 12); 
    uint32_t packetDescriptionsBytesFilled = *(uint32_t *)(ptr + 16); 

    ptr += AUDIO_BUFFER_PACKET_HEADER_SIZE; 

    // Should check for buffer overrun here 
    if (end - ptr < packetBytesFilled) 
     break; 

    const uint8_t *audioData = ptr; 

    ptr += packetBytesFilled; 

    // Check for overrun here too (combining the two checks is tricky for 32-bit pointers) 
    if (end - ptr < packetDescriptionsBytesFilled) 
     break; 

    /* Could get rid of this one too if -populatePacketDescriptionArray took a byte pointer; 
     at the very least, if you know that this NSData is never retained, you could change to 
     using +dataWithBytesNoCopy:length:freeWhenDone: to avoid unnecessary data copying */ 
    NSData *packetDescriptionsData = [NSData dataWithBytes:ptr length:packetDescriptionsBytesFilled]; 

    UInt32 inNumberPackets = packetDescriptionsBytesFilled/AUDIO_STREAM_PACK_DESC_SIZE; 
    AudioStreamPacketDescription *inPacketDescriptions; 

    inPacketDescriptions = [self populatePacketDescriptionArray:packetDescriptionsData 
             packetDescriptionNumber:inNumberPackets]; 

    if (inPacketDescriptions[0].mDataByteSize > 65536) 
    { 
     NSLog(@"packet description size is abnormally large.. soething is wrong"); 
    } 

    // Assuming no exceptions here otherwise you need @try{}[email protected]{} to call free() 
    [self handleAudioPackets:audioData 
       numberBytes:packetBytesFilled 
       numberPackets:inNumberPackets 
      packetDescriptions:inPacketDescriptions]; 

    ptr += packetDescriptionsBytesFilled; 

    free(inPacketDescriptions); 
} 

一旦你摆脱多余NSData对象,有很少的内存相关的活动你的循环中直接可见的,所以你可能泄漏的唯一的地方都在里面-populatePacketDescriptionArray:packetDescriptionNumber:-handleAudioPackets:numberBytes:numberPackets:packetDescriptions:]。或者,正如我在评论中所说,如果-handleAudioPackets:numberBytes:numberPackets:packetDescriptions:要抛出异常(在这种情况下,由于该部分周围没有@try,因此您将泄漏内存inPacketDescriptions)。