1

この問題に関連する3つのクラスがあります。私は、アプリケーション用のハードウェアサービスを実装しています。 PAPI(Platform API)は、さまざまなハードウェアインターフェイスを追跡するハードウェアサービスクラスです。私は、抽象的なHardwareInterfaceクラスとそれを派生するクラスHardwareWinUSBを実装しました。関数のコンテキストからNULLへのコンテキストの変更

以下は、私が行ったのと同様の例です。私は今、数時間のために、このと格闘してきた

class PAPI { 
    HardwareInterface *m_pHardware; 

    PAPI() { 
     m_pHardware = new HardwareWinUSB(); 
    } 

    ~PAPI() { 
     delete m_pHardware; 
    } 

    ERROR_CODE WritePacket(void* WriteBuf) 
    { 
     return m_pHardware->write(WriteBuf); 
    } 
}; 

class HardwareInterface { 
    virtual ERROR_CODE write(void* WriteBuf) = 0; 
}; 

class HardwareWinUSB : public HardwareInterface 
{ 
    ERROR_CODE write(void* Params) 
    { 
     // Some USB writing code. 
     // This had worked just fine before attempting to refactor 
     // Into this more sustainable hardware management scheme 
    { 
}; 

:私は機能は、USB接続を開くように、この問題に関連すると思われないメンバーを残してきました。これは奇妙で再現性のある問題ですが、断続的な場合があります。より高いコンテキストでデバッガをステップ実行すれば、うまく動作します。私は十分な深さを掘るしない場合は、私は

Exception thrown at 0x00000000 in <ProjectName.exe>: 0xC0000005: Access violation executing location 0x00000000 

を読み込みエラーと会ってる私はPAPIコードに掘り下げる場合、私は奇妙な行動を参照してください。 WritePacketの本体にブレークポイントを設定すると、すべてが正常に表示されます。それから、私はデバッガで "ステップオーバー"を行います。関数呼び出しからの復帰後、 'this'への参照は0x00000000に設定されます。

何が起こっていますか?リターンスタックにNULL値がプッシュされたようですか?このようなことを誰かが見たことがありますか?仮想メソッドを間違って使用していますか?

編集 さらに解剖した後、私は私が書き込みを呼び出す前に読んでいたことがわかった、と私はに読んでいたバッファは、ローカルスコープで宣言されました。新しい読み込みが入ったとき、スタックに押し込まれて破損していました。次の関数writeは破壊されたスタックに戻ります。

+0

コードのバグがどこかで起こります。一般的な園芸品種のバグの結果は、「未定義の振る舞い」であり、観察可能な結果が確かに適格となります。あなたはあなたのバグが何であるか把握するだけです。残念ながら、バグを見つけて追跡するためのペイントバイナンバーレシピはありません。もしあれば、私は仕事から外れるだろう... –

+0

あなたの返事ありがとう、サム。私はこれがバグであることを理解しています。私は約3年間、C++で専門的に仕事をしてきましたが、戻りスタックがこのように壊れてしまう問題をまだ見ていません。私は自分よりも経験豊かな人からヒントを得ることを望んでいました。「あなたの問題はあなたに問題があることです」 – Michael

答えて

0

さらに解剖した後、私はwriteを呼び出す前に読んでいることがわかりました。私が読んでいたバッファは、ローカルスコープ(read関数内)で宣言されていました。

新しい読み込みが入ったとき、スタックに読み込まれて破損していました。私が呼び出す次の関数は、破壊されたスタックに戻ります。

+0

ここであなたのソリューションを共有してくれてありがとう。可能であれば、回答を回答としてマークして、他のコミュニティメンバーに役立つようにしてください。良い一日を:) –

1

バッファオーバーランはスタック上のリターンアドレスをゴミ箱に入れることができます。あなたはvoidポインタを使ってパケットを読み書きしているようで、明示的なサイズを渡すことはないので、単純なオーバーランバグはかなり起こりそうです。 Visual Studioコンパイラには、これらの種類のバグを検出するスタック整合性チェックを追加するオプションがありますが、100%完全ではありません。それでも、電源が入っていることを確認してください。

特に、最適化されたコードをデバッグしようとしている場合は、Visual Studioデバッガでthisに間違った値が表示されることがあります。メソッドの最後に}にいる場合は、デバッガがthisの奇妙な値を示しているとは必ずしも心配しません。

+0

あなたのお返事ありがとうございます、Adrian。私は同じ考えを持っていました。これはバッファオーバーランの原因となる可能性があります。だから私はこの仮説をテストしました。これを行うために、void *パラメータをuint8_t(&Buffer)[PACKET_SIZE]に置き換えました.PACKET_SIZEは定義された定数です。これにより、私のコードは常に特定のサイズのバッファを渡すようになりました。残念ながら、これは何も変わっていないようです。私はメモリをコピーして設定するポイントを見て、彼らは私によく見えます。私がこれを見ることができる他の理由はありますか? – Michael

関連する問題