連載
» 2020年11月12日 11時00分 公開

ソフトウェア技術者のためのバグ百科事典(14)地獄の作業と化すコーディングのバグ山浦恒央の“くみこみ”な話(135)(2/3 ページ)

[山浦恒央 東海大学 大学院 組込み技術研究科 非常勤講師(工学博士),MONOist]

3.3 関数の使用方法を間違える

 関数の使用方法を間違えることがあります。例えば、引数に意図しない変数を入力する場合です(リスト3)。

#include <stdio.h>
void swap(int* x, int* y) {
	int tmp = *y;
	*y = *x;
	*x = tmp;
}
main()
{
	int LeftSide = 10, RightSide = 20;
	//swap(&LeftSide, &RightSide);としないといけなかった
	swap(LeftSide, RightSide);
}
リスト3 関数の使用方法を間違う例

 リスト3には、関数の使用方法を間違う例を示しました。swap関数では、左(LeftSide)と右(RightSide)の値を交換することを意図していますが、うまくできません。これは、関数の使用方法が間違っており、関数swapを見ると、参照渡しをする必要がありますね。つまり、「swap(&LeftSide, RightSide);」と記述します。

 意図した通りの動作になるよう、関数の使い方をしっかり把握しましょう。

3.4 記述ミスによる未定義動作

 大抵のプログラムの記述ミスは、コンパイラがエラーやワーニングで教えてくれますが、書き方によっては、エラーもワーニングも出ない場合があります。例えば、本来「if (a == b)」と書くところを「if (a = b)」とする場合です(リスト4)。

#include <stdio.h>
main(){
	int a = 0, b = 0;
	//if (a == b)と書くはずだった
	if (a = b) {	
		//aとbは同じなのでこのパスを通るはず
		printf("真");
	} else {
		//実際はこのパスを通る
		printf("偽");
	}
}
リスト4 記述ミスによる未定義動作の例

 条件式の記述ミスの例を示しました。変数aと変数bに0が入っていますので、if (a == b)と書けば、「真」となりますが、実際は、if(a = b)と書いているため、「if(0)」となり、偽のパスを通ります。

 なお、筆者の環境で動かすと、ワーニングにもエラーにもならず、「偽」と表示しました。

3.5 意図しないキャスト

 異なる型に変更する際に、変数の型をキャストします。便利な機能ですが、意図しない方に変換すると、バグとなります(リスト5)。

#include <stdio.h>
main() {
    int a = 32768;
    short b = 0;
    //意図しないキャストをしてしまった
    b = a;
    printf("b = %d\n", b);
}
リスト5 意図しないキャストの例

 リスト5には、意図しないキャストの例を示しました。short型は、2バイトなので、取り得る値は-32768から32767です。一方、int型には、32768が入っています。「b = a」とコーディングすると、取りうる値の範囲を超え、オーバーフローとなります。

 ここまで単純ミスは起こさないでしょうが、よく注意しましょう。

Copyright © ITmedia, Inc. All Rights Reserved.