バグ:文字列のコピーでやりがちな・・・

Posted: 2012年11月25日

文字列のコピーでよく指摘されているバグを紹介します。
よく指摘されているため、C言語または、C++等を使用している場合は、問題無いですが
久々に使用した時に書いてしまうこともあります。

プログラムプログラム:

 #include  <stdio.h>
 #include <stdlib.h>

 int main(int argc, char *argv[])
 {
    TCHAR szSrc = _T("12345");
    TCHAR szDest[5];

    // 文字列のコピー
    _tcscpy(szDest, szSrc);

    // 処理

    return 0;
 }

このプログラムにどのような文字列のコピーのバグがあると思いますか?

  • バッファオーバラン(配列5なのに6コピーしている)

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

 #include  <stdio.h>
 #include <stdlib.h>

 int main(int argc, char *argv[])
 {
    TCHAR szSrc = _T("12345");
    TCHAR szDest[5];

    // 文字列のコピー
    _tcsncpy_s(szDest, sizeof(szDest), szSrc, _TRUNCATE);

    // 処理

    return 0;
 }

解説解説:

_tcsncpyを用いてコピーする文字数を指定できるが
バッファーが小さい場合は、文字列配列の最後がNULLにはならないため
そのままprintfなどの関数に渡すとゴミがついた文字列が表示される(例 12345イガ魏)

そのため、_tcsncpy_sを用いることで最後にNULLをつける指定ができます。
その指定方法は、第四引数に「_TRUNCATE」をつけるだけです。
文字列配列の最後にNULLがつけた場合の結果は、「1234」となります。
「5」が表示されない理由は、「5」は「NULL」に置き換わるためです。
_TRUNCATEはこの例で言えば「5 – 1」と同意です。

もちろん、最後にNULLが必要がない場合もありますのでその場合は、_tcsncpyと使用することを薦めます。
NULLが必要ない場合とはどういう場合かと言いますと、メモリーに制限があるためNULL文字を省略したい等。
※NULL文字の省略は、バグの発生する可能性が飛躍的に上がるためあまりお勧めできません。
 strlenなど標準関数が正しい結果を返さない場合があります。

C++などでは、CStringやSTLのstringクラスが用意されているため
そちらを主に使用して
標準関数を使用する場合のみchar,wchar_tの文字列を使用することを薦めます。

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

コメント