0

何度も寄せられた質問を投稿して申し訳ありません (10 ページを読んだだけです) が、解決策が見つかりません。

OpenGL と Portaudio をそれぞれ使用して、マルチスレッドのグラフィック/オーディオ プログラムに取り組んでいます。オーディオ スレッドは、オーディオ処理オブジェクト用に私が作成しているライブラリを使用します。SIGSEGV はおそらく 20% の確率で発生し (デバッグ時ははるかに少ない)、オーディオ オブジェクトのロードを新しいストリーム情報 (サンプル レート、ベクター サイズなど) でリセットするときに発生します。Code::blocks Debugger は、障害が発生するたびに、別の場所から発生したものとして障害を示します。

これはオーディオ処理ループです。

while(true){
    stream->tick();
    menuAudio.tick();
    {
        boost::mutex::scoped_lock lock(*mutex);
        if(channel->AuSwitch.resetAudio){
            uStreamInfo newStream(channel->AuSwitch.newSrate, 
                 channel->AuSwitch.newVSize, channel->AuSwitch.newChans);
            menuAudio.resetStream(&newStream);
            (*stream) = newStream;
            menuAudio.resetStream(stream);
            channel->AuSwitch.resetAudio = false;
        }
    }
}

オーディオをリセットするように伝えるグラフィックス スレッドからの情報をチェックし、パッチ オブジェクトの resetStream 関数を実行します。これは基本的にオーディオ オブジェクトのベクトルであり、それぞれを実行します。

void uPatch::resetStream(uStreamInfo* newStream)
{
    for(unsigned i = 0; i < numObjects; ++i){
/*This is where it reports this error: Program received signal SIGSEGV,  
Segmentation fault. Variables: i = 38, numObjects = 43 */
        objects[i]->resetStream(newStream); 
    }
}  

SIGSEGV が別の場所から発信されていると表示されることもありますが、デバッガーで実行したときにエラーが発生することはめったにないため、これだけが発生する可能性があります。

非常に多くのオブジェクトがあるため、すべてのリセット コードを投稿することはしませんが、例として:

void uSamplerBuffer::resetStream(uStreamInfo* newStream)
{
    audio.set(newStream, false);
    control.set(newStream, true);
    stream = newStream;
    incr = (double)buffer->sampleRate / (double)stream->sampleRate;
    index = 0;
}

audio.set コードは次のとおりです。

void uVector::set(uStreamInfo* newStream, bool controlVector)
{
    if(vector != NULL){
        for(unsigned i = 0; i < stream->channels; ++i)
            delete[] vector[i];
        delete vector;
    }
    if(controlVector)
        channels = 1;
    else
        channels = newStream->channels;
    vector = new float*[channels];
    for(unsigned i = 0; i < channels; ++i)
        vector[i] = new float[newStream->vectorSize];
    stream = newStream;
    this->flush();
}

私の最善の推測では、実際には多数のオブジェクトでのみ発生し、それぞれが個別に正常に実行されるため、これはスタック オーバーフローの問題であると考えられます。とはいえ、オーディオ ストリーム自体は正常に動作し、同様の方法で実行されます。また、ループはobjects[i]->resetStream(newStream);各メンバー関数の後にスタックをポップする必要があるため、SIGSEGV になる理由がわかりません。

所見/推奨事項はありますか?

編集:

これは、誤って削除されたメモリの問題でした。Application Verifier は、他の場所から発生したと特定された時折の障害ではなく、エラーの時点で障害を起こしました。問題は、uVector ストリーム設定関数にありました。このクラスの意図は、stream->channels制御信号に 1 次元配列を使用するオプションを使用して、多次元配列を使用するオーディオ ベクトルを対象としているためです。メモリを再割り当てするために削除するときに、ストリーム->チャネルを使用して削除するタイプに関係なく、すべてのuVectorを誤って設定しました。

if(vector != NULL){
    for(unsigned i = 0; i < stream->channels; ++i)
        delete[] vector[i];
    delete vector;
}

あるべき場所:

if(vector != NULL){
    for(unsigned i = 0; i < this->channels; ++i)
        delete[] vector[i];
    delete vector;
}

そのため、アクセスしてはならないメモリを削除していたため、ヒープが破損していました。深刻な問題のように見えるので、セグメンテーション違反が定期的に発生していないことに驚いています。

4

2 に答える 2

0

スタックオーバーフローの問題にしたと思います。:)

深刻なことに、このようなバグは通常、オブジェクトが存在しないメモリ位置にあるオブジェクトにアクセスした結果です。最初のコード ブロックでは、スタック上で作成していることがわかりますnewStream。スコープは、それが含まれる if ステートメントに限定されています。次に、それを逆参照ポインター ( ) にコピーします*streamuStreamInfoクラスに対して安全で正しい割り当てが定義されていますか? 明示的に定義されていない場合、コンパイラはオブジェクトの割り当てのためにメンバーごとのコピーを静かに提供しintますdouble*streamによって割り当てられたメモリへのポインタが残っている可能性がありますがnewStream、その後、次の場合に割り当てが解除されますnewStream対象外になりました。現在、その RAM のデータはまだそこにあり、しばらくは正しいように見えますが、メモリの割り当てが解除されているため、クラッシュの直前など、いつでも破損する可能性があります。:)

オブジェクトの割り当てと割り当て解除のタイミング、およびどのオブジェクトが他のオブジェクトを所有しているかに細心の注意を払うことをお勧めします。大部分のコードをコメントアウトし、クラッシュが再び発生し始めるまで、徐々にコードを有効化する分割統治アプローチを採用することもできます。バグは、最近再有効化されたコードにある可能性があります。

于 2012-04-26T06:41:33.653 に答える
0

メモリを節約できれば、 Electric Fence (またはDUMA 、その子) などのツールを試して、実行する範囲外の書き込みかどうかを確認できます。通常、これらのタイプのセグメンテーション違反 (永続的ではなく、時々発生するだけ) は、どこかで以前のバッファ オーバーフローの遺物です。

上記の 2 つのツールと同じ効果を持つ Valgrind も試すことができますが、実行が遅くなります。

また、これが発生した場合にアクセスしている不正なアドレスの値を確認してください: 有効に見えますか? 発生しているバグについて、値が非常に有益な場合があります (通常、0x12 でメモリにアクセスしようとすると、0X12 はループ内のカウンターになります:))。

スタック オーバーフローの場合...問題のあるスレッドのスタック サイズを増やしてみることをお勧めします。バグが再現されるかどうかを確認してください。何度も試行しても問題が解決しない場合は、問題が見つかりました。

窓に関しては:

于 2012-04-26T06:32:13.253 に答える