• 検索結果がありません。

警告メッセージ

ドキュメント内 note.dvi (ページ 177-181)

6.21 デバッグの手法

6.21.2 警告メッセージ

C言語の警告メッセージは,バグの原因を指摘していることが多い. そのため,警告メッセージを減らす ことはバグを取り除くために有用な方法である. gccにおいて,全ての警告を出力するには,コンパイル時 に-Wall オプションをつける.

頻繁にお目にかかる警告メッセージには,以下のようなものがある.

1. 関数宣言に関わるメッセージ. (重大度:中)

gccでは“implicit declaration of function”と表示される.

戻り値がintである関数の場合には問題が生じないが,そうでない関数の場合にはエラーとなる潜在 的危険性がある.

gccでは“implicit declaration of function”と表示されるエラーとなる場合もある. この場合には,

“type mismatch with previous implicit declartion”

“previouly implicitly declaration”

などという警告と同時に発生する.

2. 未使用の変数の存在. (重大度:小)

gccでは“unused variable”と表示される.

未使用の変数はメモリエリアを圧迫する可能性がある. また,プログラムコードが醜くなる.

3. 関数引数の型の不一致. (重大度:大)

gccでは“incompatible type for argument”と表示される. また, “different type arg”と表示される こともある.

4. ポインタの型の不一致. (重大度:大)

gccでは“assignment makes pointer from *** without a cast”と表示される.

Example 6.21.6 “implicit declaration of function” の例.

int main(int argc, char **argv) {

printf("\n") ; return 0 ; }

test.c: In function ‘main’:

test.c:3: warning: implicit declaration of function ‘printf’

#include <stdio.h> がないため, printf 関数の前方宣言がない. そのため, 関数宣言に矛盾が生じて いる.

Example 6.21.7 “implicit declaration of function” でエラーとなる例.

#include <stdio.h>

int main(int argc, char **argv) {

int i ; a() ; return 0 ; }

void a() {

return ; }

test.c: In function ‘main’:

test.c:5: warning: implicit declaration of function ‘a’

test.c:4: warning:

unused variable ‘i’

test.c: At top level:

test.c:10: warning: type mismatch with previous implicit declaration test.c:5: warning: previous implicit

declaration of ‘a’

test.c:10: warning: ‘a’ was previously

implicitly declared to return ‘int’

関数aには前方宣言が存在していない. そのため,一旦はintと理解してコンパイルされるが,その後void と宣言されるため矛盾が生じる.

Example 6.21.8 “incompatible type for argument” の例.

#include <stdio.h>

#include <stdlib.h>

int main(int argc, char **argv) {

double x,y;

x = atoi(y) ; return 0 ; }

test.c: In function ‘main’:

test.c:6: incompatible type for argument 1 of ‘atoi’

atoi関数は,引数はchar *である.

Example 6.21.9 “different type”の例.

#include <stdio.h>

int main(int argc, char **argv) {

int i,j ;

printf("%d, %f\n", i,j) ; return 0 ;

}

test.c: In function ‘main’:

test.c:5: warning: double format, different type arg (arg 3)

printf関数の第3引数と,第2引数の%表示が対応していない.

Example 6.21.10 ポインタの型の不一致の例.

#include <stdio.h>

int main(int argc, char **argv) {

int i, *p ; p = i ; return 0 ; }

test.c: In function ‘main’:

test.c:5: warning: assignment makes

pointer from integer without a cast

「5行目」のポインタ代入は明らかな間違いである. もし,int *pのかわりにint p[10]とするとエラー となるが,ポインタ形式の場合にはエラーではなく, 警告となることに注意.

ポインタ代入に関しては,型が異ると常にこの警告が出てくる.

Example 6.21.11 -ansi -pedanticオプションをつけずにコンパイルしたときには問題がないが,-ansi

-pedanticオプションをつけるとコンパイルできない例.

#include <stdio.h>

int main(int argc, char **argv) {

int n, a[n] ; return 0 ; }

test.c: In function ‘main’:

test.c:5: warning: ANSI C forbids variable-size array ‘a’

ANSI Cでは可変サイズの配列は認められていない. C++では可変サイズの配列が認められているため,

-ansi -pedanticをはずすと警告が出てこない.

6.21.2.1 リンクエラー

リンク時のエラーは,コンパイルしたコードとライブラリを結合する際に,全てのシンボル名(名前)を 解決出来ないことが原因となる.

Example 6.21.12

#include <stdio.h>

#include <math.h>

int main(int argc, char **argv) {

printf("%f\n", sqrt(2.0)) ; return 0 ;

} を gcc test.c

としてコンパイルすると,

Undefined first referenced

symbol in file

sqrt /var/tmp/ccx1zyDC.o

ld: fatal: Symbol referencing errors. No output written to a.out collect2: ld returned 1 exit status

というリンクエラーが発生する.

この例では, 数学関数sqrt というシンボルが解決できていない. 数学関数を利用する場合には, リンク 時に-lmというオプションを最後につけなければならない.

gcc test.c -lm

とすればエラーは解決できる.

Example 6.21.13

/* test0.c */

#include <stdio.h>

int a=1 ;

int main(int argc, char **argv) {

a = 2 ; return 0 ; }

/* test1.c */

#include <stdio.h>

int a=1 ;

int main(int argc, char **argv) {

a = 2 ; return 0 ; }

gcc -c test0.c gcc -c test1.c

gcc test0.o test1.o -o a.out としてコンパイルすると,

ld: fatal: symbol ‘a’ is multiply defined:

(file test.o and file test1.o);

ld: fatal: symbol ‘main’ is multiply defined:

(file test.o and file test1.o);

ld: fatal: File processing errors. No output writt というリンクエラーが発生する.

この例は2つエラーがあり,

main 関数が2つのコードにあり,エントリポイントを決定できない.

静的変数 aがともに初期化されているため,両方の変数aのリンケージが決定できない.

第2の問題を解決するには,どちらかで初期化をやめることになる.

ドキュメント内 note.dvi (ページ 177-181)