2

デバッグ中に「バッファが小さすぎます」というエラーをスローし続けるこのコードがあります。

        geoGraph.size=limit;
        CString xAxis ="X axis: ",yAxis="Y axis: ";

        for (int x = 0; x < limit; x++)
        {

            xAxis.Format(_T("%s%i  "),xAxis,(x+1));
            yAxis.Format(_T("%s%s  "),yAxis,dialog_test.str[x]);

        }

        xAxis.Format(_T("%s \n%s  "),xAxis,yAxis);// <---Error thrown

        d.SetWindowTextA(xAxis);

エラーは、Cstring xAxis が小さすぎて新しいテキストを含めることができないという事実によるものであるという結論に達しました。私は正しいですか?もしそうなら、どうすれば修正できますか?


ありがとう。

編集:なぜこのエラーがデバッグ中にのみ表示され、「デバッグなしで開始」でアプリケーションを実行しているときは表示されないのか(私はVS2008を使用しています)。

4

4 に答える 4

10

いいえ!本当の問題は次のとおりです。

  1. xAxis Format が開始され、さらに余裕が必要であることがわかります。Format に指定されたすべてのパラメータの計算に基づきます。
  2. xAxis ストレージが再割り当てされます。古いポインタは無効になり、デバッグ バージョンではそれを解放して上書きします。したがって、0 ターミネータはもうありません。メモリは、空きメモリの標準値で満たされます。
  3. フォーマットは、古いポインター (変更されたばかりのコンテンツ) から開始して収集し、ゴミをコピーして、0 ターミネーターを見つけません。

Format で CString をターゲットおよびソースとして使用しないでください。メモリが変更されない可能性があるため、これはリリース バージョンで機能する可能性がありますが、変更された場合の動作は未定義です。しかし、これは本当に悪いコーディング バグです。

于 2013-10-08T06:01:18.463 に答える
2

CStringT::Formatのドキュメントには、次のコメントが含まれています。

文字列オブジェクト自体が Format のパラメーターとして提供されている場合、呼び出しは失敗します。たとえば、次のコードは予測できない結果を引き起こします。

CAtlString str = _T("Some Data");
str.Format(_T("%s%d"), str, 123);
// Attention: str is also used in the parameter list.

これを回避するには、引数のコピーを作成するか、この特定のケースでは代わりにCStringT::AppendFormatクラス メンバーを呼び出します。

geoGraph.size = limit;
CStringW xAxis = L"X axis: ",
         yAxis = L"Y axis: ";

for ( int x = 0; x < limit; ++x ) {
    xAxis.AppendFormat( L"%i  ", x + 1 );
    yAxis.AppendFormat( L"%s  ", dialog_test.str[x].GetString() );
}

xAxis.AppendFormat( L" \n%s  ", yAxis.GetString() );

特に、この実装はCSimpleStringT::GetString%sを呼び出して、書式指定子で使用する C スタイルの文字列を取得することに注意してください。CStringプレースホルダーのオブジェクトを渡すことは、動作するように%s文書化されていません*

また、この実装では、CStringオブジェクトの明示的なワイド文字バージョンと、ワイド文字列リテラルが使用されていることに注意してください。サポートされているすべてのバージョンの Windows は、ネイティブ エンコーディングとして Unicode (UTF-16) を使用します。したがって、アプリケーションで Unicode を使用することは自然な選択です。


* 現在サポートされている ATL/MFC のすべてのバージョンは、C スタイルの文字列が期待される場所ならどこでもオブジェクトCStringを渡すことができるように実装されています。CStringこれは可変引数リストでも機能します。後者は実装の詳細であり、文書化された契約の一部ではありません。依存すべきではありません。

于 2016-07-27T11:56:25.593 に答える