2014-01-21 3 views
0

Im работает над потоковым мультимедиа-приложением. Im в настоящее время получает признаки огромных утечек памяти. Инструменты говорят, что это связано с приведенным ниже кодом. Во время цикла 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

Вы создаете в этом цикле огромное количество временных объектов; если некоторые из них попадают в пул авторесурсов, а не явно -release d, они собираются накапливаться, потому что у вас нет @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: должны были выбросить исключение (в этом случае вы пропустите память для inPacketDescriptions, потому что вокруг этой части нет @try).

Смежные вопросы