прерывистый extaudiofileread exc_bad_access - PullRequest
4 голосов
/ 12 октября 2011

У меня есть то, что на данный момент кажется неразрешимой проблемой EXC_BAD_ACCESS. Я попытался включить NSZombie, как кажется, совет во многих постах, но я имею дело с указателями c, а не с объектными объектами, поэтому я не получаю никакой полезной информации отладки.

Способ, которым работает мой код, состоит в том, что перед тем, как ему понадобится немного аудио с диска, я отсоединяю новый поток posix, передавая ему указатель на информацию об аудио, которое я хочу. Затем я прочитал несколько образцов. Причина, по которой я выбрал posix вместо NSThread или NSOperation, заключается в том, что он, кажется, работает быстрее. Мой звук довольно интенсивный, поэтому мне нужно читать аудио как можно быстрее.

Как я могу исправить эту ошибку неверного доступа? Это не происходит все время. Иногда это происходит, когда приложение очень загружено. Очень редко это вообще не происходит.

В любом случае, я мог бы просто попытаться исправить это как быстрое решение? Как еще я могу выяснить причины этого?

Редактировать Это ссылка на отдельный вопрос, который я задал, но он связан с той же проблемой

[Threading для интенсивного ввода] [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 

Ответы [ 4 ]

1 голос
/ 28 октября 2011

В конце концов я нашел решение этой проблемы.Каждый раз, когда мне нужно было аудио, я создавал новый поток для получения аудио.В некоторых случаях, когда поток извлекал аудио для определенного буфера, тот же буфер запрашивал данные снова, в результате чего доступ к одному и тому же буферу выполнялся в одно и то же время, поэтому exc_bad_access.

Я решил эту проблему, имея только один потокожидание и получение сигнала для получения данных с использованием условия posix.

Все ответы здесь были полезны и помогли мне многое узнать об отладке.Спасибо, ребята ..

1 голос
/ 25 октября 2011

Я заметил следующие строки в вашем коде:

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

Вы используете malloc'а для AudioBufferList, чтобы иметь емкость одного AudioBuffer, но затем указывает, что он на самом деле имеет два. Попробуйте изменить это "* (1)" на "* (2)".

В дополнение к этому, вы не должны выполнять malloc или ExtAudioFileOpen в потоке, так как они будут занимать время. Если вам удастся предварительно выполнить malloc и ExtAudioFileOpen и просто сохранить их в массиве struct для ваших файлов, вы можете обнаружить увеличение производительности / стабильности.

Возможно, я не полностью прочитал код, так как похоже, что форматирование немного испортилось, но я надеюсь, что это поможет.

1 голос
/ 25 октября 2011

Вы исправляете это, находя его и выясняя, почему это не так, а не пытаясь поймать.

Guard Malloc может помочь вам определить многие проблемы в вашей программе. Это диагностическая опция, которую вы можете включить в Xcode. Цель этого параметра - потерпеть неудачу при попытке чтения или записи не принадлежащей вам памяти, что делает более понятным, чем обычно, какую часть вашей программы вызывает проблемы. полная информация: man guardmalloc. Первый шаг - исправить все проблемы, на которые указывает guardmalloc. Вы сможете часами запускать ваше приложение без этих проблем.

Если вы хотите, чтобы исключения и проверки во время выполнения помогли вам выявить эти проблемы раньше (что заслуживает вашего внимания), рассмотрите C ++, а не C для ваших реализаций.

Обновление

Если это выделение кучи, то это выделение, о котором идет речь, вероятно, вам поможет регистрация по malloc. когда ведение журнала malloc включено и отладчик приостанавливает выполнение, просто используйте malloc_history для просмотра стека вызовов для выделения. malloc_history выполнит поиск адреса в журнале и выдаст стэк вызова создания alloc. оттуда, вы просто следите за потоком выделения через вашу программу, чтобы найти то, что вы ошибаетесь.

0 голосов
/ 12 октября 2011

Проблема почти наверняка возникает, потому что ваша память чтения не должна быть. Отсюда EXC_BAD_ACCESS. Важно, чтобы размеры ваших буферов и объем памяти, который вы читаете, были правильными. Например, если вы попытаетесь прочитать больше, чем стоит буфер, вы получите ошибку.

В ExtAudioFileRead значение в &readoutpt2 должно указывать количество кадров. Вы уверены, что это значение верно? bufferList достаточно большой, чтобы хранить это количество кадров? Вы продвигаете указатель через bufferList, когда читаете данные, и правильно ли вы переводите сумму?

Правильно ли вы выделяете память в зависимости от базового типа? Например, ваши аудиоданные целочисленные или в формате с плавающей запятой?

В общем, все должно складываться правильно, иначе вы где-нибудь создадите буфер!

Еще один инструмент для отслеживания проблем с памятью - guard malloc. Вы можете найти больше информации здесь Включение функций отладки Malloc

...