3

私はこれに数日間困惑しています。クラスの1つで単体テストを実行して、すべてが正しいことを確認しています。

ただし、オブジェクトの名前を比較すると、非常に奇妙な「バグ」が発生します。名前はコンストラクターを呼び出すときに設定されます。名前は、渡したメモに基づいて正しく設定されています。ただし、この場合、BOOST_CHECKは失敗します。

これがどれほど奇妙かを示すために、デバッガーの2つの文字列の値を次に示します。

Fdim.name() // "F Diminished"
BOOST_CHECK(Fdim.name() == "F Diminished");  // this fails

デバッガーから取得した2つの文字列の仕様は次のとおりです。

Fdim.name() 
// size - 12, capacity - 15, 
// chars: [70, 32, 68, 105, 109, 105, 110, 105, 115, 104, 101, 100]

"F Diminished" stored inside a variable (to see specs of string)
// size - 12, capacity - 15,
// chars: [70, 32, 68, 105, 109, 105, 110, 105, 115, 104, 101, 100]

ご覧のとおり、文字列は同じですが、==と.compareはどちらも失敗します。

これはさらに奇妙なことです:

std::string n = Fdim.name();
std::string r = "F Diminished";
unsigned val = n.compare(r);       // RETURNS 0, everytime
BOOST_CHECK(val == 0);             // fails 
BOOST_CHECK(val == ((unsigned) 0));// fails

私は完全に唖然としている。文字列を比較するとき(つまり等しい)、valは常に0を返しますが、比較するときはval!= 0?

誰かが問題が何であるか知っていますか?この比較チェックを失敗させる可能性があることについて知っておくべき文字列の属性はありますか?

EDIT ***文字列はstd::stringとして保存されています 、私はchar*またはcstringを使用していませんmember_nameはstd::stringです。

ブースト出力は次のとおりです。

c:/directory etc(64): error in "ChordIdentification": check val == 0 failed
c:/directory etc(65): error in "ChordIdentification": check n == r failed
c:/directory etc(66): error in "ChordIdentification": check val == ((unsigned) 0) failed
c:/directory etc(67): error in "ChordIdentification": check Fdim.name() == "F Diminished" failed

これがテストケースのコードです。val、n、rが何であるかを人々が知っていることを確認するためです。

BOOST_AUTO_TEST_CASE(ChordIdentification)
{
MAKE_NOTE(Db, 'D', FLAT);   // macro that creates a note
MAKE_NOTE(F, 'F', NATURAL);
MAKE_NOTE(Ab, 'A', FLAT);
MAKE_NOTE(Cb, 'C', FLAT);

Chord DbMajor7 = Chord(Cb, Ab, F, Db);
Chord Fdim = Chord(Ab, Cb, F);

CHORD_TEST(DbMajor7, "Db Dominant7", MAJ, THIRD_INVERSION, DOMINANT7); macro of several boost tests, checking members. This test passes completely for this instance of chord. name() check is passed
std::string n = Fdim.name();
std::string r = "F Diminished";
unsigned val = n.compare(r);
//if (val == 0)
BOOST_CHECK(val == 0);
BOOST_CHECK(n == r);
BOOST_CHECK(Fdim.name() == std::string("F Diminished"));    // these strings fail to compare. no idea why, lengths are same, chars same?????
BOOST_CHECK(std::strcmp(Fdim.name(), "F Diminished") == 0);
CHORD_TEST(Fdim, "F Diminished", DIM, FIRST_INVERSION, DIMINISHED); // partially successful, again the string comparison is responsible for this
}
4

2 に答える 2

4

私はついにこれが起こった理由を発見しました。これは、デバッガーが評価しようとしている子クラスのインスタンスを判別できなかったという事実と関係がありました。

コードは、マップ、ポリモーフィックキー、抽象基本クラス(Composite_Key)、子(Composite_Key_2Intervals)、およびその子の子(Composite_Key_3Intervals)を介して識別されます。

失敗したのは、キーが実際に3間隔、つまり2であるかどうかに関するあらゆる種類のテストが、3intervals:2intervalsであるため、常にtrueを返していたという事実でした。コンパイラはこれを検出できず、ルックアップテーブルで見つかった間違った値を常に返していました。

また、マップはデバッガーモードでソートされなかったため、キーが挿入された順序は同じままでした。ただし、実際にはそれらは再シャッフルされていたため、デバッグ中の評価全体が完全に誤りになりました。

これを修正するために、これら2つのクラスが抽象ベースからのみ継承されるようにして、相互に関連しないようにしました。これで、すべてのテストに合格し、すべてが真に戻ります。

この問題のこの原因は、デバッガーのみでした。適切に評価されませんでした。

于 2013-01-20T21:11:35.767 に答える
2

これを見ると:

BOOST_CHECK(Fdim.name() == "F Diminished")

その場合、Fdim.name()はCスタイルの文字列であると私は期待しています。したがって、文字配列への単なるポインタです。その文字配列のアドレスは、(ほとんどの場合)のリテラル文字列と同じアドレスではありませんBOOST_CHECK()

あなたはそれを修正することができます:

BOOST_CHECK(Fdim.name() == string("F Diminished"))

また

BOOST_CHECK(strcmp(Fdim.name(), "F Diminished") == 0)
于 2013-01-20T19:40:40.863 に答える