【问题标题】:intermittent extaudiofileread exc_bad_access间歇性 extaudiofileread exc_bad_access
【发布时间】:2011-10-28 16:59:16
【问题描述】:

目前我遇到了一个似乎无法解决的 EXC_BAD_ACCESS 问题。 我已经尝试启用 NSZombie,这似乎是许多帖子中的建议,但我处理的是 c 指针而不是 obj c 对象,所以我没有得到任何有用的调试信息。

我的代码的工作方式是,在它需要一些来自磁盘的音频之前,我分离了一个新的 posix 线程,向它传递一个指向我想要的音频信息的指针。然后我读了一些样本。 我之所以选择 posix 而不是 NSThread 或 NSOperation 是因为它似乎执行得更快。我的音频占用大量 CPU,因此我需要尽快读取音频。

如何解决这个错误的访问错误?它不会一直发生。有时它似乎发生在应用程序非常繁忙的时候。偶尔它根本不会发生。

无论如何我可以尝试解决这个问题作为快速解决方案吗?我还能如何调查造成这种情况的原因?

编辑这是我提出的一个单独问题的链接,但它与同一个问题有关

[密集 io 线程][1]

//detachnewthread gets called from remoteio callback

void detachnewthread(AudioSourceOBJ str)
{

    //..... code removed for brevity
    if(str)
    {

        int rc;

        rc = pthread_create(&str->thread, NULL, FetchAudio, (void *)str);
        if (rc){
            printf("ERROR; return code from pthread_create() is %d\n", rc);
            exit(-1);
        }

    }

}


void *FetchAudio(void *threadid)

{ AudioSourceOBJ soundptr=threadid;

AudioUnitSampleType *outSamplesChannelLeft;
AudioUnitSampleType *outSamplesChannelRight;

outSamplesChannelLeft                 = (AudioUnitSampleType *) soundptr->queuebuffer->ABL->mBuffers[0].mData;
outSamplesChannelRight  = (AudioUnitSampleType *)soundptr->queuebuffer->ABL->mBuffers[0].mData;
// ExtAudioFileRef audioFileRef;



// result=  ExtAudioFileOpenURL(str->path, &str->audioFileObject);

AudioStreamBasicDescription importFormat = {0};

size_t bytesPerSample = sizeof (AudioUnitSampleType);

// Fill the application audio format struct's fields to define a linear PCM, 
//        stereo, noninterleaved stream at the hardware sample rate.
importFormat.mFormatID          = kAudioFormatLinearPCM;
importFormat.mFormatFlags       = kAudioFormatFlagsAudioUnitCanonical;
importFormat.mBytesPerPacket    = bytesPerSample;
importFormat.mFramesPerPacket   = 1;
importFormat.mBytesPerFrame     = bytesPerSample;
importFormat.mChannelsPerFrame  = 2;                    // 2 indicates stereo
importFormat.mBitsPerChannel    = 8 * bytesPerSample;
importFormat.mSampleRate        = 44100;


ExtAudioFileSetProperty (
                                     engineDescribtion.audiofilerefs[soundptr->audioindex],
                                     kExtAudioFileProperty_ClientDataFormat,
                                     sizeof (importFormat),
                                     &importFormat
                                     );

UInt32 numberofframestoread=(soundptr->amounttoread);
AudioBufferList *bufferList;

bufferList = (AudioBufferList *) malloc (
                                         sizeof (AudioBufferList) + sizeof (AudioBuffer) * (1)
                                         );


// initialize the mNumberBuffers member
bufferList->mNumberBuffers = 2;

// initialize the mBuffers member to 0
AudioBuffer emptyBuffer = {0};
size_t arrayIndex;
for (arrayIndex = 0; arrayIndex < 2; arrayIndex++) {
    bufferList->mBuffers[arrayIndex] = emptyBuffer;
}

// set up the AudioBuffer structs in the buffer list
bufferList->mBuffers[0].mNumberChannels  = 1;
bufferList->mBuffers[0].mDataByteSize    = numberofframestoread * sizeof (AudioUnitSampleType);
bufferList->mBuffers[0].mData            = (AudioUnitSampleType*)calloc(numberofframestoread, sizeof(AudioUnitSampleType));

    bufferList->mBuffers[1].mNumberChannels  = 1;
    bufferList->mBuffers[1].mDataByteSize    = numberofframestoread * sizeof (AudioUnitSampleType);
    bufferList->mBuffers[1].mData            = (AudioUnitSampleType*)calloc(numberofframestoread, sizeof(AudioUnitSampleType));




AudioUnitSampleType *inSamplesChannelLeft=bufferList->mBuffers[0].mData;
AudioUnitSampleType *inSamplesChannelRight=bufferList->mBuffers[1].mData;



// UInt32 read=(UInt32)soundptr->fetchsample;
UInt32 read_plus_half_buffer=soundptr->fetchsample;

UInt32 readdestination= read_plus_half_buffer+numberofframestoread;
UInt32 actualsamplesread=0;

actualsamplesread=numberofframestoread;


if (readdestination>soundptr->perfectframecount) {


    UInt32 readinpt1=0;
    UInt32 readoutpt1=0;
    UInt32 readinpt2=0;
    UInt32 readoutpt2=0;
    Float32 readtillendamount=0;

    readinpt1=read_plus_half_buffer;
    readoutpt1=soundptr->perfectframecount;
    readinpt2=0;



    if(read_plus_half_buffer>soundptr->perfectframecount)
    {
        readtillendamount=numberofframestoread;
        readinpt1=read_plus_half_buffer-soundptr->perfectframecount;

    }else
    {

        readtillendamount=soundptr->perfectframecount - readinpt1;
        readoutpt2=numberofframestoread-readtillendamount;




    }
    actualsamplesread= readtillendamount;
    ExtAudioFileSeek(engineDescribtion.audiofilerefs[soundptr->audioindex], readinpt1);
    ExtAudioFileRead(engineDescribtion.audiofilerefs[soundptr->audioindex],&actualsamplesread , bufferList);

    int writeposition=soundptr->queuebuffer->position;

    for (int i=0; i<actualsamplesread; i++) {


        outSamplesChannelLeft[writeposition]=inSamplesChannelLeft[i];
        outSamplesChannelRight[writeposition]=inSamplesChannelRight[i];



        writeposition++;

    }

    if (actualsamplesread!=readtillendamount) {

        UInt32 newzeroamount= readtillendamount-actualsamplesread;

        for (int j=0; j<newzeroamount; j++) {

            outSamplesChannelLeft[writeposition]=0;
            outSamplesChannelRight[writeposition]=0;
            writeposition++;

        }

    }       
    bufferList->mBuffers[1].mDataByteSize    = readoutpt2 * sizeof (AudioUnitSampleType);
    bufferList->mBuffers[0].mDataByteSize    = readoutpt2 * sizeof (AudioUnitSampleType);


    ExtAudioFileSeek(engineDescribtion.audiofilerefs[soundptr->audioindex], 0);
    ExtAudioFileRead(engineDescribtion.audiofilerefs[soundptr->audioindex],&readoutpt2 , bufferList);


    for (int k=0; k<readoutpt2; k++) {

        outSamplesChannelLeft[writeposition]=inSamplesChannelLeft[k];
        outSamplesChannelRight[writeposition]=inSamplesChannelRight[k];
        writeposition++;

    }


}else if(readdestination<=soundptr->perfectframecount){

    ExtAudioFileSeek(engineDescribtion.audiofilerefs[soundptr->audioindex], read_plus_half_buffer);

    bufferList->mBuffers[1].mDataByteSize    = actualsamplesread * sizeof (AudioUnitSampleType);
    bufferList->mBuffers[0].mDataByteSize    = actualsamplesread * sizeof (AudioUnitSampleType);
    // crash happens here

    if(bufferList)
    {
   assert( ExtAudioFileRead(engineDescribtion.audiofilerefs[soundptr->audioindex],&actualsamplesread , bufferList));
    }else

    {
        printf("NO BUFFER");
    }



    int writeposition=soundptr->queuebuffer->position;
    for (int i=0; i<actualsamplesread; i++) {

        outSamplesChannelLeft[writeposition]=inSamplesChannelLeft[i];
        outSamplesChannelRight[writeposition]=inSamplesChannelRight[i];
        writeposition++;

    }

    if (actualsamplesread!=numberofframestoread) {
        int zerosamples=0;

        zerosamples=numberofframestoread-actualsamplesread;

        for (int j=0; j<zerosamples; j++) {
            outSamplesChannelLeft[writeposition]=0;
            outSamplesChannelRight[writeposition]=0;
            writeposition++;


        }

    }                

}else
{
    printf("unknown condition");

}





free(bufferList->mBuffers[0].mData); 
free(bufferList->mBuffers[1].mData); 
free(bufferList);
bufferList=nil;

soundptr->queuebuffer->isreading=NO;

// pthread_detach(soundptr->thread);  
// free(&soundptr->m_lock);
return 0;
// pthread_exit(NULL);

}

编辑 2

好的,我已经弄清楚了如何使用 malloc 历史记录。我有一个很大的跟踪声明。这是我以前第一次看到这样的东西,我不知道如何用它来帮助自己。

    ALLOC 0x6c67000-0x6c67fd7 [size=4056]: thread_a019c540 |start | main | UIApplicationMain | GSEventRun | GSEventRunModal | CFRunLoopRunInMode | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoSource1 | __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ | migHelperRecievePortCallout | _XReceivedStatusBarDataAndActions | _UIStatusBarReceivedStatusBarDataAndActions | -[UIStatusBarServer _receivedStatusBarData:actions:] | -[UIStatusBarForegroundView setStatusBarData:actions:animated:] | -[UIStatusBarLayoutManager updateItemsWithData:actions:animated:] | -[UIStatusBarLayoutManager _updateItemView:withData:actions:animated:] | -[UIStatusBarItemView updateContentsAndWidth] | -[UIStatusBarTimeItemView contentsImageForStyle:] | -[UIStatusBarItemView drawText:forStyle:] | -[UIStatusBarItemView drawText:forStyle:forWidth:lineBreakMode:letterSpacing:] | -[NSString(UIStringDrawing) drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:] | -[NSString(UIStringDrawing) drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:] | -[NSString(WebStringDrawing) _web_drawAtPoint:forWidth:withFont:ellipsis:letterSpacing:includeEmoji:] | -[NSString(WebStringDrawing) __web_drawAtPoint:forWidth:withFont:ellipsis:letterSpacing:includeEmoji:measureOnly:] | -[NSString(WebStringDrawing) __web_drawAtPoint:forWidth:withFont:ellipsis:letterSpacing:includeEmoji:measureOnly:renderedStringOut:] | drawAtPoint(unsigned short const*, int, WebCore::FloatPoint const&, WebCore::Font const&, WebCore::GraphicsContext*, WebCore::BidiStatus*, int) | WebCore::Font::drawSimpleText(WebCore::GraphicsContext*, WebCore::TextRun const&, WebCore::FloatPoint const&, int, int) const | WebCore::Font::drawGlyphBuffer(WebCore::GraphicsContext*, WebCore::GlyphBuffer const&, WebCore::TextRun const&, WebCore::FloatPoint&) const | WebCore::Font::drawGlyphs(WebCore::GraphicsContext*, WebCore::SimpleFontData const*, WebCore::GlyphBuffer const&, int, int, WebCore::FloatPoint const&, bool) const | WebCore::showGlyphsWithAdvances(WebCore::FontPlatformData const&, CGContext*, unsigned short const*, CGSize const*, unsigned long) | CGContextShowGlyphsWithAdvances | draw_glyphs | ripc_DrawGlyphs | ripc_RenderGlyphs | CGGlyphLockLockGlyphBitmaps | create_missing_bitmaps | CGFontCreateGlyphBitmap8 | aa_create | malloc | malloc_zone_malloc 
----
FREE  0x6c67000-0x6c67fd7 [size=4056]: thread_a019c540 |start | main | UIApplicationMain | GSEventRun | GSEventRunModal | CFRunLoopRunInMode | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoSource1 | __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ | migHelperRecievePortCallout | _XReceivedStatusBarDataAndActions | _UIStatusBarReceivedStatusBarDataAndActions | -[UIStatusBarServer _receivedStatusBarData:actions:] | -[UIStatusBarForegroundView setStatusBarData:actions:animated:] | -[UIStatusBarLayoutManager updateItemsWithData:actions:animated:] | -[UIStatusBarLayoutManager _updateItemView:withData:actions:animated:] | -[UIStatusBarItemView updateContentsAndWidth] | -[UIStatusBarTimeItemView contentsImageForStyle:] | -[UIStatusBarItemView drawText:forStyle:] | -[UIStatusBarItemView drawText:forStyle:forWidth:lineBreakMode:letterSpacing:] | -[NSString(UIStringDrawing) drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:] | -[NSString(UIStringDrawing) drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:] | -[NSString(WebStringDrawing) _web_drawAtPoint:forWidth:withFont:ellipsis:letterSpacing:includeEmoji:] | -[NSString(WebStringDrawing) __web_drawAtPoint:forWidth:withFont:ellipsis:letterSpacing:includeEmoji:measureOnly:] | -[NSString(WebStringDrawing) __web_drawAtPoint:forWidth:withFont:ellipsis:letterSpacing:includeEmoji:measureOnly:renderedStringOut:] | drawAtPoint(unsigned short const*, int, WebCore::FloatPoint const&, WebCore::Font const&, WebCore::GraphicsContext*, WebCore::BidiStatus*, int) | WebCore::Font::drawSimpleText(WebCore::GraphicsContext*, WebCore::TextRun const&, WebCore::FloatPoint const&, int, int) const | WebCore::Font::drawGlyphBuffer(WebCore::GraphicsContext*, WebCore::GlyphBuffer const&, WebCore::TextRun const&, WebCore::FloatPoint&) const | WebCore::Font::drawGlyphs(WebCore::GraphicsContext*, WebCore::SimpleFontData const*, WebCore::GlyphBuffer const&, int, int, WebCore::FloatPoint const&, bool) const | WebCore::showGlyphsWithAdvances(WebCore::FontPlatformData const&, CGContext*, unsigned short const*, CGSize const*, unsigned long) | CGContextShowGlyphsWithAdvances | draw_glyphs | ripc_DrawGlyphs | ripc_RenderGlyphs | CGGlyphLockLockGlyphBitmaps | create_missing_bitmaps | CGFontCreateGlyphBitmap8 | aa_destroy | free 

ALLOC 0x6c67000-0x6c67fff [size=4096]: thread_b024f000 |thread_start | _pthread_start | __NSThread__main__ | -[NSThread main] | -[FirstViewController checkstate:] | CALayer_setter_kCAValueFloat | CALayer_setter | CA::Transaction::ensure_compat() | CA::Transaction::create() | malloc | malloc_zone_malloc 
----
FREE  0x6c67000-0x6c67fff [size=4096]: thread_b024f000 |thread_start | _pthread_start | __NSThread__main__ | -[NSString compare:options:] | _pthread_exit | _pthread_tsd_cleanup | free 

ALLOC 0x6c67000-0x6c67fff [size=4096]: thread_b0353000 |thread_start | _pthread_start | __NSThread__main__ | -[NSThread main] | -[FirstViewController checkstate:] | CALayer_setter_kCAValueFloat | CALayer_setter | CA::Transaction::ensure_compat() | CA::Transaction::create() | malloc | malloc_zone_malloc 
----
FREE  0x6c67000-0x6c67fff [size=4096]: thread_b0353000 |thread_start | _pthread_start | __NSThread__main__ | -[NSString compare:options:] | _pthread_exit | _pthread_tsd_cleanup | free 

ALLOC 0x6c67000-0x6c67fff [size=4096]: thread_b0763000 |thread_start | _pthread_start | FetchAudio | ExtAudioFileRead | ExtAudioFile::Read(unsigned long, unsigned long&, AudioBufferList*) | AudioConverterFillComplexBuffer | BufferedAudioConverter::FillBuffer(unsigned long&, AudioBufferList&, AudioStreamPacketDescription*) | AudioConverterChain::RenderOutput(CABufferList*, unsigned long, unsigned long&, AudioStreamPacketDescription*) | BufferedAudioConverter::FillBuffer(unsigned long&, AudioBufferList&, AudioStreamPacketDescription*) | CBRConverter::RenderOutput(CABufferList*, unsigned long, unsigned long&, AudioStreamPacketDescription*) | BufferedAudioConverter::GetInputBytes(unsigned long, unsigned long&, CABufferList const*&) | CABufferList::AllocateBuffers(unsigned long) | operator new[](unsigned long) | operator new(unsigned long) | malloc | malloc_zone_malloc 
----
FREE  0x6c67000-0x6c67fff [size=4096]: thread_b0763000 |thread_start | _pthread_start | FetchAudio | ExtAudioFileRead | ExtAudioFile::Read(unsigned long, unsigned long&, AudioBufferList*) | AudioConverterFillComplexBuffer | BufferedAudioConverter::FillBuffer(unsigned long&, AudioBufferList&, AudioStreamPacketDescription*) | AudioConverterChain::RenderOutput(CABufferList*, unsigned long, unsigned long&, AudioStreamPacketDescription*) | BufferedAudioConverter::FillBuffer(unsigned long&, AudioBufferList&, AudioStreamPacketDescription*) | CBRConverter::RenderOutput(CABufferList*, unsigned long, unsigned long&, AudioStreamPacketDescription*) | BufferedAudioConverter::GetInputBytes(unsigned long, unsigned long&, CABufferList const*&) | free 

ALLOC 0x6c67000-0x6c67fff [size=4096]: thread_b0a6f000 |thread_start | _pthread_start | FetchAudio | ExtAudioFileRead | ExtAudioFile::Read(unsigned long, unsigned long&, AudioBufferList*) | AudioConverterFillComplexBuffer | BufferedAudioConverter::FillBuffer(unsigned long&, AudioBufferList&, AudioStreamPacketDescription*) | AudioConverterChain::RenderOutput(CABufferList*, unsigned long, unsigned long&, AudioStreamPacketDescription*) | BufferedAudioConverter::FillBuffer(unsigned long&, AudioBufferList&, AudioStreamPacketDescription*) | CBRConverter::RenderOutput(CABufferList*, unsigned long, unsigned long&, AudioStreamPacketDescription*) | BufferedAudioConverter::GetInputBytes(unsigned long, unsigned long&, CABufferList const*&) | CABufferList::AllocateBuffers(unsigned long) | operator new[](unsigned long) | operator new(unsigned long) | malloc | malloc_zone_malloc 
----
FREE  0x6c67000-0x6c67fff [size=4096]: thread_b0a6f000 |thread_start | _pthread_start | FetchAudio | ExtAudioFileRead | ExtAudioFile::Read(unsigned long, unsigned long&, AudioBufferList*) | AudioConverterFillComplexBuffer | BufferedAudioConverter::FillBuffer(unsigned long&, AudioBufferList&, AudioStreamPacketDescription*) | AudioConverterChain::RenderOutput(CABufferList*, unsigned long, unsigned long&, AudioStreamPacketDescription*) | BufferedAudioConverter::FillBuffer(unsigned long&, AudioBufferList&, AudioStreamPacketDescription*) | CBRConverter::RenderOutput(CABufferList*, unsigned long, unsigned long&, AudioStreamPacketDescription*) | BufferedAudioConverter::GetInputBytes(unsigned long, unsigned long&, CABufferList const*&) | free 

ALLOC 0x6c67000-0x6c67fff [size=4096]: thread_b0081000 |thread_start | _pthread_start | __NSThread__main__ | -[NSThread main] | -[FirstViewController checkstate:] | CALayer_setter_kCAValueFloat | CALayer_setter | CA::Transaction::ensure_compat() | CA::Transaction::create() | malloc | malloc_zone_malloc 
----
FREE  0x6c67000-0x6c67fff [size=4096]: thread_b0081000 |thread_start | _pthread_start | __NSThread__main__ | -[NSString compare:options:] | _pthread_exit | _pthread_tsd_cleanup | free 

【问题讨论】:

  • '似乎执行得更快' - 除非您非常快速地创建线程,否则我非常怀疑用于创建线程的方法会影响它们的性能。但是,请用一些基准证明我错了;)
  • 您认为快速多快?我每秒分离大约 16 - 24 个线程。是不是太过分了?
  • 我认为这有点过分,是的。我会考虑重新考虑架构——有这么多线程,创建线程的成本将开始超过它们的好处。您可以按顺序执行什么操作,从而减少创建的线程数?
  • 感谢您的意见。好吧,我有 0 到 20 个音频文件需要随时读取。 Prehaps 我可以尝试只使用 1 个单一的生产者线程并从中为它们提供服务。我担心它不会足够快地执行。或者也许我可以让一个线程不断地为每一位音频运行,并使用标志来指示他们是否应该休眠或获取音频?你认为有这么多线程可能与我的内存访问问题有关吗?

标签: iphone ios exc-bad-access


【解决方案1】:

我注意到您的代码中有以下几行:

bufferList = (AudioBufferList *) malloc (
                                         sizeof (AudioBufferList) + sizeof (AudioBuffer) * (1)
                                         );
// initialize the mNumberBuffers member
bufferList->mNumberBuffers = 2;

您将 AudioBufferList 分配为具有一个 AudioBuffer 的容量,但随后表明它实际上有两个。尝试将“* (1)”更改为“* (2)”。

除此之外,您不应在线程中执行 malloc 或 ExtAudioFileOpen,因为它们会占用时间。如果您可以设法预先执行 malloc 和 ExtAudioFileOpen,并将它们保存在文件的结构数组中,您可能会发现性能/稳定性有所提高。

我可能没有完全正确地阅读代码,因为它看起来格式有点混乱,但我希望这会有所帮助。

【讨论】:

    【解决方案2】:

    您可以通过定位并找出错误的原因来解决此问题,而不是通过 try/catch。

    Guard Malloc 可以帮助您识别程序中的许多问题。这是一个可以在 Xcode 中启用的诊断选项。该选项的目的是在您尝试读取或写入不属于您的内存时失败,从而比通常更清楚您的程序的哪个部分导致了问题。完整详情:man guardmalloc。第一步是纠正所有 guardmalloc 指出的问题。您应该能够在没有这些问题的情况下运行您的应用数小时。

    如果您希望异常和运行时检查帮助您尽早识别这些问题(这值得您考虑),请考虑使用 C++ 而不是 C 来实现您的实现。

    更新

    如果问题分配是堆分配,那么 malloc 日志记录可能会对您有所帮助。当启用 malloc 日志并且调试器暂停执行时,只需使用 malloc_history 查看分配的调用堆栈。 malloc_history 将在日志中查找地址并转储 alloc 创建的调用堆栈。从那里,您只需按照分配流程在您的程序中查找错误。

    【讨论】:

    • 我在使用 malloc 提供的信息时遇到了问题。提供了一个内存地址,向我展示了 malloc 发生的位置。 (不确定这是否与 exc_bad_access 有关)。我已经设置了一个断点并查看了调试器中所有对象的内存地址,但我永远找不到与错误中的地址匹配的对象。
    • 我收到这条消息“malloc:recording malloc stacks to disk using standard recorder”。在哪里可以查看已录制的内容?
    • @dubbeat man malloc 秒。环境。好奇的可以偷看,但是有程序(比如malloc_history)使用会更容易。
    【解决方案3】:

    我最终找到了解决这个问题的方法。每次我需要音频时,我都会创建一个新线程来获取音频。有时,当线程为特定缓冲区获取音频时,同一缓冲区会再次请求数据,从而导致同一缓冲区同时被访问,因此出现 exc_bad_access。

    我通过让一个线程等待并被通知使用 posix 条件获取数据来解决这个问题。

    这里的所有答案都很有用,帮助我了解了很多关于调试的知识。谢谢各位。。

    【讨论】:

    • 太好了,你把它整理好了!我一有空就去看这个。也就是说,我可能不会有太多帮助,因为我认为这很可能是缓冲区大小计算问题。
    • 好消息。我建议您将您的答案标记为已接受,这样它就不会继续出现在未回答的列表中... :)
    【解决方案4】:

    这个问题几乎肯定会发生,因为你的阅读记忆是你不应该的。因此EXC_BAD_ACCESS。重要的是缓冲区的大小和正在读取的内存量都是正确的。例如,如果您尝试读取超过缓冲区的值,则会收到错误消息。

    ExtAudioFileRead 中,&amp;readoutpt2 的值应指定帧数。你确定这个值是正确的吗? bufferList 是否足够大以存储该数量的帧?您在读取数据时是否通过bufferList 推进指针,推进的数量是否正确?

    您是否根据基础类型正确分配内存?比如你的音频数据是整数还是浮点格式?

    基本上,所有东西都需要正确加起来,否则你会在某处炸毁缓冲区!

    另一个尝试追踪内存问题的工具是guard malloc。你可以在这里找到更多信息Enabling the Malloc Debugging Features

    【讨论】:

    • 是的,我确定 readoutpt2 的值是正确的,我的缓冲区列表也是如此。
    • 样本是什么格式的?整数还是浮点数?您对缓冲区分配的计算是什么?有多少个频道?
    • 样本是有符号的 16 位整数,2 个音频通道。作为最佳猜测,您会说问题与缓冲区列表有关,而不是与从磁盘读取的实际音频有关吗?如果我同时访问 8 个音频源,一切都很好。除此之外,我得到了错误。是否有可能由于线程中缺乏资源代码没有完全执行,例如:缓冲区的创建
    • 我会说它更有可能与缓冲区有关。它们有多大?你是如何计算它们的大小的?
    • 每个 buff 的最大大小为 25600 个样本 * 4 个字节。我已经在帖子中包含了完整的功能。可能比试图解释更容易看。
    猜你喜欢
    • 1970-01-01
    • 2021-08-31
    • 1970-01-01
    • 1970-01-01
    • 2021-07-15
    • 2012-10-20
    • 2018-12-16
    • 2019-01-18
    • 1970-01-01
    相关资源
    最近更新 更多