バグ:文字列の連結で問題はありますか?

Posted: 2013年02月18日

文字列操作(連結)で書いてしまうバグを紹介します。

プログラムプログラム:

 #include <stdio.h>

 int main(int argc, char *argv[])
 {
    CString strSrc = _T(" ABCDEFG "); // 全角空白

    for (int nIndex = 0; nIndex < 100; nIndex++) {
        strSrc.Append(_T("HIJK"));
    }
    // 処理

    return 0;
 }

このプログラムにどのように文字列操作(連結)にバグが存在すると思いますか?

  • 大量に連結することがわかっている場合処理に時間がかかる
  • 大量に連結する場合、メモリー確保失敗することを想定していない

改善版プログラム改善版プログラム:

 #include <stdio.h>

 int main(int argc, char *argv[])
 {
    CString strSrc = _T(" ABCDEFG "); // 全角空白

    strSrc.GetBuffer(100 * 4); // おおよその領域を確保
    try {
        for (int nIndex = 0; nIndex < 100; nIndex++) {
            strSrc.Append(_T("HIJK"));
        }
    } catch (CMemoryException *pEx) {
        // 例外処理
        pEx->Delete();
    }
    strSrc.ReleaseBuffer();

    // 処理

    return 0;
 }

解説解説:

Appendでは、確保済みの領域が足りない場合realloc(領域の再確保)を行います。
事前に大量の連結がわかっている場合は、GetBufferを行い事前に流域を確保します。
GetBufferには、最小のサイズを指定しますが
ゆとりを持ったほうがreallocをせずに処理が行われるため、パフォーマンスは良くなります。
しかし、メモリーを大量に取り過ぎると確保できない場合もあるため
それぞれの場合に合わせてサイズを検討する必要があります。

念の為書いておきますがGetBuffer後のAppendでは、領域が足りない場合は
reallocが行われるためGetBufferの引数の値をそこまで悩まなくてもいいです。

GetBufferを行った場合はReleaseBufferを行う必要があります。

カテゴリー: バグ, プログラム | タグ: , , , | コメント無し »

コメント