3

私は 3rd-Pary ライブラリの巨大なクラスを使用しています。関連するものの抜粋を次に示します。

class SomeClass {
    // ...
public:
    // ...
    virtual int SetTableSize(unsigned int uiTableID, int iSize);
    // ...
protected:
    // ...
    virtual int Set_0xB0_0x23_IsoTableData(unsigned char* ucData, int iLen);
    // ...
};

アプリケーションがメモリ アクセス違反で壊れます。コール スタックの一番上の項目は の実装のコード行でSet_0xB0_0x23_IsoTableData、2 番目の項目は次のようなコード行です。

someClassInstance.SetTableSize(2, 400);

デバッグ ビューでucDataは、値0x00000002が であるため、実際には の実装を呼び出す代わりにSetTableSize、コードに従って発生する必要があるように見えSet_0xB0_0x23_IsoTableDataますが、指定されたパラメーターで呼び出されます。ポインターが有効でないため、明らかにエラーが発生します。

ここで何が起こるかを理解するために、私はすでに多くの時間を費やしてきました。Linux で GCC を使用して別のアプリケーション内で同じコードをコンパイルすると、そこで動作します。これは Visual Studio コンパイラのバグですか? このコードをコンパイルしても、警告は表示されません。

バグを再現するための最小限の作業例を作成することはできません-少なくとも、これが発生する理由を理解するまでは. SomeClassヘッダーにはかなりの数#ifdefの s が含まれているため、最初に思ったのは、プリプロセッサの定義はSomeClass、呼び出し元のコードをコンパイルするときと、含まれているモジュールをコンパイルするときでは異なるということでした。ただし、再確認したところ、定義は同じです。

だから私が聞きたいのは基本的に:

  • 仮想メソッドの呼び出しが別の仮想メソッドの実装を呼び出すことができる条件は? (これは継承に関するものではありません。2 つのメソッドは同じクラスで定義されており、シグネチャを共有しておらず、可視性も異なります)
  • このようなエラーをデバッグするにはどうすればよいですか? クラス インスタンスのディスパッチ ベクターを Visual Studio で表示することはできますか?
4

1 に答える 1

0

この種の問題に対する私の標準的な答えは、すべてを再構築することです。場合によっては、それはそれと同じくらい単純/愚かです (少なくとも Visual Studio の場合)。

エラーがまだ残っている場合は、デバッグを行います。「今までに発生したことはありません」と言える限り、コードを実行します。次に、1 行ずつ、1 行ずつデバッグし、コール スタックを注意深く監視します。

いいえ、これは楽しくありません。

于 2014-03-12T10:06:09.067 に答える