0

Matrix22配列とデフォルトのコンストラクターを持つC++クラスがあります。

class Matrix22{
  /* something more */
  double mat[2][2];
  Matrix22(){
    for(int i=0; i<2; i++)
      for(int j=0; j<2; j++)
        mat[i][j] = i==j ? 1.0 : 0.0;
  }
};

プログラムで使用しましたが、セグメンテーション違反が発生しました。残りは非常に難しく複雑だったので、私は単純なテストルーチンを作成しましたMatrix22()。セグメンテーション違反はもうありません。

次にgdb、問題をデバッグするために実行しました。別のテストルーチンからコンストラクターを呼び出すとgcc、メンバー用にメモリが予約されmatます。スタックをナビゲートして、配列の数バイト後のリターンアドレスを確認できます。

メインプログラムでは、コンパイラは十分なスペースを予約していません。最初の要素(mat[0][0])が書き込まれますが、それ以降の書き込みは次のスタックフレームを上書きするだけです。また、コンストラクターの前と同様に、コマンドbtが正しいバックトレースを返すことを確認できます。重要な割り当ての後、バックトレースが破損しています。

だから私の質問は:なぜある場合にはコンパイラ(またはリンカ?)が配列のために十分なスペースを予約しないのに、他の場合にはそれが起こらないのですか?

PS:両方の「テストケース」は同じコンパイラとフラグでコンパイルされ、同じオブジェクトファイルに対してもリンクされています。

編集:

セグメンテーション違反なしで機能する「単純な」テストケースは次のとおりです。

void test_Matrix22()
{
  Framework::Math::Matrix22 matrix;
}

セグメンテーション違反を作成するコードは、クラスModuleShaddower(混合ヘッダーと実装)にあります。

class ModuleShaddower{
    public:
        ModuleShaddower(PVModule& module, const EnvironmentalSetup& setup, const Position& position);
    private:
        Matrix22 rotMatrix90;
};

ModuleShaddower::ModuleShaddower(PVModule& module, const EnvironmentalSetup& setup, const Position& position)
  : module (module), position(position), setup(setup), logger(LoggerFactory::getLoggerInstance())
{
    double mat[][2] = {{0, -1},{1, 0}}; // This line will never be reached
    rotMatrix90 = Matrix22(mat);
}

ご覧のとおり、それは残りの部分からかなりのものです。問題のあるコードを抽出しようとするかもしれませんが、これはあまり役に立たないと思います。

4

2 に答える 2

0

ModuleShaddowerコンストラクターコードに到達していない場合(コードコメントによる)、コンストラクター初期化リスト内の何か(モジュールの構築、位置などに関連する)が問題の原因です。

于 2012-04-10T16:16:58.463 に答える
0

問題は、異なる場所にある2つのオブジェクトファイルが同じ名前であるという事実が原因でした。そのオブジェクトコードから作成された結果の静的ライブラリでは、間違ったファイルが置き換えられることがあります(両方とも呼び出されましたShaddower.o)。ファイルの名前を変更すると、すべてうまくいき、エラーはなくなりました。

この問題の正確な原因はわかりませんが、そのように解決できます。

于 2012-04-19T06:52:51.867 に答える