【C++】char配列をフォーマット指定で書き込むときの注意

C++(しーぷらすぷらす)

とあるC++ソースの不具合を調査をしていたところ、おかしな動きをしている箇所があった。

サンプルソース

// 変数宣言
char strA[] = "12345678";
char strB[8];
char ret[16];

// 初期化
memset(strB, 0x00, sizeof(strB));
memset(ret, 0x00, sizeof(ret));

// "12345678"をchar[8]の配列にコピー
memcpy(strB, strA, sizeof(strB));

// char[8]の内容をシングルクォーテーションで囲ってchar[16]の配列へ
sprintf(ret, "'%s'", strB);

// char[16]の配列を返す
return ret;

こんな感じのソースで、retの値に「’12345678’」が入ることを期待していたんだけど、変な値で返ってくる…。

サンプルソースで書いてしまえば一目瞭然なんだけど、実際のソースはもっと複雑なのと、SDLチェックも外されていたので、原因に気付くまで時間がかかった。

原因は文字列の終端文字分のサイズが考慮されていないこと

C言語やC++では、文字列に「終端文字」と呼ばれる「\0」(ヌル文字)を最後に付ける必要がある。

なので、例えば最大8文字入る変数は、プラス終端文字分でサイズを9用意する必要がある。
そうしないと、文字列の終端が捉えられず、正しいデータを取得できなくなってしまう。

ちなみに、上記サンプルソースのうち、

char strA[] = "12345678";

のように、サイズを省略して指定した場合、9扱いとなる。

投稿者: Output48

中学生の時に初めてHTMLに触れてからホームページ制作を独学で始める。 ベンチャー企業の営業、大手企業のPG・SEを経て、独立。 現在はとある企業のCTOと、変な名前の会社の社長をしてる。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください