2014-01-21 110 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)。