バグ:文字列中にnullが存在する文字列の扱い方

Posted: 2013年01月07日

文字列中にnullが存在する文字列の扱い方を間違えてよく書いてしまうバグを紹介します。
文字列中にnullが入っている文字列とは例えばmainの引数などです。

「cmd.exe time /T」を実行した場合

cmd.exeの引数には「cmd.exetime/T」が設定される。
通常は、この文字列を解釈する必要がないためこの処理で苦労することはありません

プログラムプログラム:

 #include <stdio.h>

 int CountWord (const TCHAR *pData)
 {
    int nLength = _tcslen(pData);
    int nWordCount = 0;

    for (int nIndex = 0; nIndex < nLength; nIndex++) {
        if (*(pData + nIndex) == _T('\0')) {
            // 単語の最後が見つかった(\0)
            nWordCount++;
        }
    }
 }

 int main(int argc, char *argv[])
 {
    const TCHAR *pszSrc = _T("Green\0Red\0Blue");

    int nWordCount = CountWord(pszSrc);

    return 0;
 }

このプログラムにどのように文字列中にnullが存在する文字列の扱い方を間違えていると思いますか?

  • CountWordの_tcslenは(null)までのバイト数を返すためこの場合Greenまでの「5」を返すため期待と異なる処理が行われる

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

 #include <stdio.h>

 int CountWord (const TCHAR *pData, const int nLength)
 {
    int nWordCount = 0;

    for (int nIndex = 0; nIndex < nLength; nIndex++) {
        if (*(pData + nIndex) == _T('\0')) {
            // 単語の最後が見つかった(\0)
            nWordCount++;
        }
    }
 }

 int main(int argc, char *argv[])
 {
    const TCHAR szSrc[] = _T("Green\0Red\0Blue");

    int nWordCount = CountWord(pszSrc, sizeof(szSrc) / sizeof(TCHAR));

    return 0;
 }

解説解説:

変更としては、呼び出し側がサイズを渡すようにし、CountWordの問題がを取り除きました。

呼び出し側は、どのようにサイズを取得するか
文字列ポインターではサイズがわからないため配列に変更し、
sizeofを用いて配列のサイズを取得しています。

その他文字列クラスCStringなどは、を基準で行なっているためGetLengthも同様だと思われます。
※実際にどう動作するか確認したほうがいいと思います!!

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

コメント