3

現在、かなりのプログラムをデバッグしています。次のコード行に到達すると:

value->binary_string = value_it->binary_string.substr(range->msb->value, range->size);

プログラムが正しく動作しません。ここで、value は、std::string 型の binary_string という名前のメンバーを持つ構造体へのポインターです。デバッグ中にこの行に到達すると、次のことがわかります。

value_it->binary_string = "00000000000000000000000000000111"
range->msb->value = 0
range->size = 32

このコード行の実行後、value->binary_string は空です! 行を次のように変更しました

value->binary_string = value_it->binary_string

それでも失敗します!

デバッグ中にこの行に到達すると、私のプログラムは約 100 Mb のメモリを使用しているため、メモリの問題ではないと思います (ただし、これを確認するために Valgrind を実行しています)。Ubuntu 11.10、g++-4.6、および libstdc++6 を使用しています。

誰もこのようなことに遭遇したことがありますか?ストリングが機能しない理由がわかりません。

ありがとう、

サム

EDIT1:

値のタイプは NumberInst で、以下に定義されています。

typedef std::string String;

struct NumberInst
{
    unsigned size;
    bool signed_;
    String binary_string;
    bool valid;
    unsigned value;

    NumberInst();
};

EDIT2:

少し絞って検索したようです。デバッグ中に、いくつかの印刷コマンドを試しました。

print value_it->binary_string
"00000000000000000000000000000111"
print value_it->binary_string[31]
'1'
print value_it->binary_string.substr(0, String::npos)
""
print value_it->binary_string.substr(0, 1)
""

このコンテキストでは substr が正しく機能していないようです。しかし、メイン関数で substr をテストしたところ、問題なく動作しているように見えました。

4

2 に答える 2

2

このような「奇妙な」ことが起こるとき、通常は 2 つの一般的な理由があることがわかりました。

  1. あなたは単純な間違いを犯し、それを見落としているだけです。
  2. ある種のメモリ破損。

最初の理由を確認するには、問題のあるコードを注意深く読み、コードが何をしているのかを意識して判断し、コードが何をすべきだと考えているかではありません。特にしばらく見てきたコードでは、コードが実際にはしていないことをしているはずだと思い込んで、明らかなエラーを見落としがちです。たとえば、数か月前、何かをデバッグしていて、変数の値が突然「魔法のように」変化するという問題がありました。間違った変数を出力していたことがわかりました (当然です!) コードが実際に何を言っているのかを読んでいれば、これをもっと早く見つけられたでしょう。

メモリの破損は、問題が発生する前にいつでも実行されているコードの一部から発生する可能性があるため、見つけるのが難しい獣です. Valgrind は、すべての形式の破損を検出することを保証するものではありません。例については、この質問を参照してください。デバッグ モードでの実行、メモリ ウォッチ ポイントの設定 (破損が常に発生する場所がわかっている場合)、およびその他のメモリ関連ツールが問題を最小限の形に減らすのに役立つ場合があります...破損が発生するまで、実行されるコードを少しずつ削除し続けます起こりません。

于 2012-03-01T23:01:36.340 に答える
1

この問題は、非常に微妙なバグによって引き起こされました。私のプロジェクトのどこかに:

NumberInst* number = new NumberInst;
number->binary_string.reserve(size);
for (unsigned i = 0; i < size; i++)
    number->binary_string[i] = ...;

std::out_of_range 例外はスローされません。これは、標準ライブラリが配列インデックスを (文字列のサイズではなく) 文字列の容量と比較すると想定しているためです。デバッガーでの print の呼び出しは成功します。おそらく、'\0' 文字に到達するまでバッファーを反復処理するためです。でも

String str = number->binary_string

標準ライブラリが value_it->binary_string のバッファを [0, size) からコピーし、'\0' 文字を追加する可能性が高いため、失敗します。value_it->binary_string のサイズが 0 であるため、その内容のコピーは失敗します (呼び出し文字列のサイズに依存する substr やその他の関数と同様)。

つまり、問題は呼び出しによって引き起こされました

str.reserve(size);

それ以外の

str.resize(size);

助けてくれてありがとう!

サム

于 2012-03-02T17:01:57.583 に答える