連載
» 2019年02月22日 10時00分 公開

バグ検出ドリル(15)なぜ「山田三郎」が「まだまだ天田三郎」に化けるのか山浦恒央の“くみこみ”な話(115)(3/3 ページ)

[山浦恒央 東海大学 大学院 組込み技術研究科 非常勤講師(工学博士),MONOist]
前のページへ 1|2|3       

4.今回の解答

 「山田三郎」が、「まだまだ天田三郎」になっていますね。この原因は、「strcatにより、隣接する文字列を書き換えてしまっている」です。

 問題を簡単に振り返ります。名前を表す変数name1〜3に、名字を表す変数familynameをそれぞれ連結し、表示します。例えば、name1にfamilynameを連結すると、IchiroYamadaになると期待しています。連結には、C言語の標準関数、strcat関数を使います。そんなに難しいプログラミングではないのに、うまく表示できません。

 正しい動作をしない原因は、隣接している文字列を書き換えているためです(いわゆる、「爆撃」ですね)。まず、以下のソースコードをご覧ください。

	// 名字
	char familyname[] = "Yamada";
	
	// 名前
	char name1[] = "Ichiro";
	char name2[] = "Ziro";
	char name3[] = "Saburo";
リスト1から抜粋

 上記の配列宣言部では、名字を表すfamilynameに「Yamada」を代入し、名前を表す配列name1〜3にそれぞれの名前を代入しています。図1に各配列の値を示します。1段目が変数名、2段目は簡易的なアドレス※3)、3段目で変数値を表示しました。

※3)筆者の環境(Cygwin GCC 7.3.0)での、各変数のアドレスの末尾2桁を記載しました。別の環境で実行すると同様の結果とならない場合があるので、ご注意ください。

図1 図1 変数値の詳細(クリックで拡大)

 図1の変数の状態で、1回目のstrcat(name1,familyname)を実行すると、図2となります。name1の18番地からYamadaが書き込まれているのが分かりますね。問題は、name1とfamilynameが、隣接していることです。strcat関数で、名字を追加するのは良いのですが、肝心のfamilynameの値を上書きし、19番地以降が、「amada」となってしまいました。

図2 図2 1回目のstrcat実行後の変数値の詳細(クリックで拡大)

 図2に対し、2回目のstrcat(name2,familyname)を実行すると、図3となります。name2の末尾の11番地にfamilynameを書き込んだ結果、隣接するname1に「amada」を上書きしてしまいました。

図3 図3 2回目のstrcat実行後の変数値の詳細(クリックで拡大)

 図3に対し、3回目のstrcat(name3,familyname)を実行すると、図4になります。この状態で、各変数を表示すると、各変数の先頭番地(6、d、12)から表示するので、「Saburoamada」「mada」「mada」と表示してしまいました。

図4 図4 3回目のstrcat実行後の変数値の詳細(クリックで拡大)

 正しい結果を出すためには、name変数の配列のサイズを大きく取っておくといいでしょう(例えば、char name1[100])。ただし、想定のサイズを超えると、同様の結果となるので注意が必要です。

5.自己採点シート

 今回の自己採点シートを以下に示します。

問題 内容 配点(点)
文字列連結プログラム 問題を一通り読んだ 50
隣接する変数の値を書き換えているバグを見つけた 50
リスト4 自己採点シート

6.終わりに

 プログラムを思い通りに作ることは簡単ではありません。今回は、文字列連結プログラムの問題を出題しました。皆さんはバグを見つけられたでしょうか。

 C/C++言語で文字列を扱う場合、strcatやstrtokなどの標準関数を使うことがあります。標準関数の中には、使い方を誤ると思わぬ誤動作につながるものがあり、注意が必要です。

 実際のソフトウェアの開発では、文字列の処理はよく出てきますね。筆者は、機器の情報を文字列で取得し、整形して使うソフトウェアを作成したことがあります。文字列を処理するプログラムでは、文字列の操作関数を注意深く使わないと、不可解なバグでたっぷり悩むことになります。お互い、気を付けましょう。

参考文献

「Cプログラミング専門課程」(藤原博文、1994年、技術評論社)

【 筆者紹介 】
山浦 恒央(やまうら つねお)

東海大学 大学院 組込み技術研究科 非常勤講師(工学博士)


1977年、日立ソフトウェアエンジニアリングに入社、2006年より、東海大学情報理工学部ソフトウェア開発工学科助教授、2007年より、同大学大学院組込み技術研究科准教授、2016年より非常勤講師。

主な著書・訳書は、「Advances in Computers」 (Academic Press社、共著)、「ピープルウエア 第2版」「ソフトウェアテスト技法」「実践的プログラムテスト入門」「デスマーチ 第2版」「ソフトウエア開発プロフェッショナル」(以上、日経BP社、共訳)、「ソフトウエア開発 55の真実と10のウソ」「初めて学ぶソフトウエアメトリクス」(以上、日経BP社、翻訳)。


前のページへ 1|2|3       

Copyright © ITmedia, Inc. All Rights Reserved.