gcc のエラーメッセージの読み方

はじめに‥‥

コンピュータを使う上で、エラーメッセージというものは避けられないものです。 大抵の人は見るのも嫌でしょう。しかしエラーメッセージには、なぜエラーになっ たかという情報が含まれています(エラーメッセージの意味がわかりにくい、不 親切なプログラムも中にはありますが)。エラーメッセージが出た場合、 見慣れないものであっても(英語であっても)、とりあえず読んでみることが大 切です。

コンパイラは gcc を使います。しかし、コンパイラのエラーメッセージは専門的な用語も多く、 入門者にとっては理解しにくいものもあるでしょう。ここでは gcc での典型的 なエラーメッセージと、その解決法について説明します。なお、このページは gcc version 2.95.2 に基づいています。
現在使用している物とメッセージが違う場合はどんどん指摘して下さい。


基本的なエラーメッセージの読み方

コンパイルをしたときに、例えば以下のようなメッセージが出たとします。

% gcc foo.c
foo.c: In function `main':
foo.c:3: `i' undeclared (first use in this function)
foo.c:3: (Each undeclared identifier is reported only once
foo.c:3: for each function it appears in.)

まず、左端の foo.c というのは、エラーがあるファイルの名前で す。次の 3 というのは、エラーのある行数です。つまり、foo.c というファイルの 3 行目にエラーがあるということになります。

また、エラーメッセージの最初の行の In function `main': というのは、「以下のエラーは main 関数の中で発生しました」 という意味です。 また、学習が進むにつれて main 関数以外の関数も作るようになります。 その時ここに表示される関数名は、エラーを見つけるのに重要な役割を果たします。

コンパイルすると、エラーメッセージが山のように出てくることがありますが、 基本的には一番最初のエラーから修正していきます。最初のエラーが原因で 他の箇所でもエラーになることもあり、最初のエラーを修正するだけで、他のエ ラーも全部消えることはよくあることです。


エラーメッセージの種類

以下では、典型的なエラーメッセージについて見ていきます。 もし見慣れないエラーメッセージが出たら、ここを参考にプログラムを修正して みてください。なお、このページのサンプルプログラムの左端の数字は行番号を表 すもので、プログラムの一部ではありません。

`i' undeclared (first use in this function)

訳: `i' が宣言されていません(この関数内で初めて使用されます)
     1  #include <stdio.h>
     2  int main(){
     3    for(i=0; i<10; i++){
     4      printf("%d\n", i);
     5    }
     6  }
% gcc undeclared.c
undeclared.c: In function `main':
undeclared.c:3: `i' undeclared (first use in this function)
undeclared.c:3: (Each undeclared identifier is reported only once
undeclared.c:3: for each function it appears in.)

これはプログラム中で使っている変数が宣言されていない場合に起こります。 関数の始めなどで、その変数を宣言してあげてください。 また、長い名前の変数や綴りが難しい変数では、タイプミスをしている可能性も あるので、その点も充分にチェックしてください。

parse error at end of input

訳: 入力の終りで構文エラー
     1  #include <stdio.h>
     2  main(){
     3    int i;
     4  
     5    for(i=0; i<10; i++){
     6      printf("%d\n", i);
     7  
     8  }
% gcc parse.c
parse.c: In function `main':
parse.c:9: parse error at end of input

9 行目でエラーとなっていますが、実際は 7 行目に } がないのが 原因です。このエラーは大抵の場合、括弧の閉じ忘れか、括弧が2バイト文字 (俗に言う全角)だったりします。どこで括弧の対応がおかしくなっているかは、 エディタのインデント機能(emacs の M-x indent-regionなど) を使うと探しやすいです(括弧の対応がおかしい部分でインデントがずれる)。

parse error before `}'

訳: `}' の前で構文エラー
     1  #include <stdio.h>
     2  int main(){
     3    int i;
     4  
     5    for(i=0; i<10; i++){
     6      printf("%d\n", i)
     7    }
     8  }
% gcc parse-before.c
parse-before.c: In function `main':
parse-before.c:7: parse error before `}'

"parse error before" 関連のエラーが出た場合は、エラーがになった行の前の 行も確認しましょう。また、} 以外だけでなく、他の文字が入る こともあります。その文字の前に間違いがないか調べてみてください。

この例では、6 行目の最後の ; が抜けてい ます。また、その } に対応する { が抜けている場 合もあるので、確認しましょう。

parse error before character 0241

訳: 文字 0241 の前で構文エラー
     1  #include <stdio.h>
     2  int main(){
     3    int i;
     4  
     5    for(i=0; i<10; i++){ 
     6      printf("%d\n", i);
     7    }
     8  }
% gcc invalid-char.c
invalid-char.c: In function `main':
invalid-char.c:5: parse error before character 0241

一見、どこにエラーがあるのか分かりにくいですが、このエラーが出た場合は 全角の文字が紛れ込んでいる可能性があります。この例では、5行目の最後に 全角スペースが入っています。この他、括弧などが全角になっている場合も、 このエラーが発生します。

unterminated string or character constant

訳: 文字定数、もしくは文字列が終わっていません
     1  #include <stdio.h>
     2  int main(){
     3    int i;
     4  
     5    for(i=0; i<10; i++){
     6      printf("%d\n, i);
     7    }
     8    printf("\n");
     9  }
% gcc unterminated.c
unterminated.c:8: unterminated string or character constant
unterminated.c:6: possible real start of unterminated constant

これは " を閉じ忘れている場合に起きます。 エラーが発生しているのは 8 行目ですが、エラーをよく見ると、 6 行目から間違っていることが読み取れます。ちゃんと " を閉じてあげてください。

undefined reference to `prnitf'

訳: `prnitf' というリファレンスは未定義です
     1  #include <stdio.h>
     2  int main(){
     3    int i;
     4  
     5    for(i=0; i<10; i++){
     6      prnitf("%d\n", i);
     7    }
     8  }
% gcc prnitf.c
/var/tmp/cciASwUT.o: In function `main':
/var/tmp/cciASwUT.o(.text+0x30): undefined reference to `prnitf'
collect2: ld returned 1 exit status

このエラーが出た場合は、大抵関数名の打ち間違いです。この例では、 printf としなければならないところを prnitf と書いてしまっています。

undefined reference to `sin'

訳: `sin' というリファレンスは未定義です
     1  #include <stdio.h>
     2  #include <math.h>
     3  int main(){
     4    double d;
     5  
     6    d=sin(3.1415926);
     7    printf("%f\n", d);
     8  }
% gcc math.c
/var/tmp/ccWDmq5o.o: In function `main':
/var/tmp/ccWDmq5o.o(.text+0x10): undefined reference to `sin'
collect2: ld returned 1 exit status

これは 「undefined reference to `prnitf'」と ほぼ同じですが、関数名が sin になっています。 sin()、cos()、tan() など(他にもたくさんあります)の数学関数を使う場合に は、コンパイルするときに -lm というオプションを付ける必要が あります。また、#include <math.h> を始めに書くのも忘 れないようにしてください。

% gcc math.c -lm
% ./a.out
0.000000

Segmentation Fault

訳: セグメント例外
     1  #include <stdio.h>
     2  int main(){
     3    int i;
     4  
     5    scanf("%d", i);
     6  }
% gcc seg_fault.c
% ./a.out
1
Segmentation Fault

このエラーはメモリに不正なアスセスをした場合に発生します。 ポインタを習うまでは、このエラーが出た場合は大抵 scanf の引数の & の付け忘れです。この例では、 scanf("%d", i); ではなく、scanf("%d", &i); とすることにより、正しいプログラムになります。

それ以外でこのエラーが出た場合は、エラー箇所を探すのには苦労することがあ ります。デバッガ(例えば gdb など)を使えば、すぐに見つけることができる ので、 デバッガの使い方 を修得することをお薦めします。

/usr/include/stdio.h:261: parse error before `__va_list'

訳: /usr/include/stdio.h の 261 行目の `__va_list' の前で構文エラー
     1  /* Here is comment.      */
     2  /* Here is also comment. */ Here is not comment.
     3  
     4  #include <stdio.h>
     5  int main(){
     6    int i;
     7  
     8    for(i=0; i<10; i++){
     9      printf("%d\n", i);
    10    }
    11  }
% gcc va_list.c
va_list.c:2: parse error before `is'
In file included from va_list.c:4:
/usr/include/stdio.h:261: parse error before `__va_list'
/usr/include/stdio.h:262: parse error before `__va_list'
/usr/include/stdio.h:265: parse error before `__va_list'
/usr/include/stdio.h:267: parse error before `__va_list'

このエラーが出た場合は、ファイルの先頭の #include <stdio.h> の前におかしな文字が入っていなか調べてみましょう。 この例では、#include 文の上にコメントが書いてありますが、 コメント部分以外にもコメントが書かれています。