我正致力于音乐流媒体应用。我目前收到巨大内存泄漏的迹象。仪器说它与下面的代码有关。在while循环期间分配了一些内存块。我打开了ARC。我已经用尽所有选项,需要更多的想法
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 :(得分:1)
你在那个循环中创建了大量的临时对象;如果其中一些最终出现在自动释放池中而不是明确地-release
d,那么它们会累积,因为你的循环中没有@autoreleasepool
。严格来说,这不是内存泄漏本身(因为它最终会被释放),但它可能看起来像是仪器中的一个。
尝试重写一下你的循环,删除一些不必要的NSData
对象。 e.g:
[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{}...@finally{} to call free()
[self handleAudioPackets:audioData
numberBytes:packetBytesFilled
numberPackets:inNumberPackets
packetDescriptions:inPacketDescriptions];
ptr += packetDescriptionsBytesFilled;
free(inPacketDescriptions);
}
一旦你摆脱了额外的NSData
个对象,你的循环中几乎没有可见的内存相关活动,所以你可以泄漏的唯一地方是-populatePacketDescriptionArray:packetDescriptionNumber:
和{{1} }}。或者,正如我在评论中所说,如果-handleAudioPackets:numberBytes:numberPackets:packetDescriptions:]
要抛出异常(在这种情况下,你会泄漏-handleAudioPackets:numberBytes:numberPackets:packetDescriptions:
的内存,因为该部分周围没有inPacketDescriptions