[[Cygwinでデバッグ]] #contents ** エラーの出る場合 [#f7c1399d] エラーは、大きく分けて3通りあります。コンパイル時のエラーと、リンク時のエラーと、実行時のエラーです。 + コンパイル時のエラーは、原因の特定に役立つことが多いです。 + リンク時のエラーは、メッセージが不親切ですが、原因の特定は簡単です。 + 実行時のエラーは厄介で、どこでエラーが起こったのかわかりにくく、苦労することが多いです。 エラーメッセージを、そのまま Google などの検索エンジンに放り込んでみる、という手法も効果的です。見たことのないエラーメッセージに対しては、ぜひ試してみるべきでしょう。 *** コンパイル時のエラー [#a9c8ad20] コンパイル時のエラーは、言語の文法上の間違いによって起こります。エラーメッセージは、多くの場合は原因の特定に役立ちますので、しっかりと読んでみましょう。分からない単語は辞書で引いてみるのもよいでしょう。 'parse', 'array', 'argument', 'redeclaration' などの単語は、日常英会話では使いませんが、プログラマとしてはぜひとも知っておくべきです。 また、エラーメッセージは最初のものから対処することが重要です。なぜなら、最初のエラーに対処すれば、その後のエラーが直ってしまうことも多々あるからです。カッコの抜けで起こるエラーでよくあります。 また、エラーメッセージは最初のものから対処することが重要です。なぜなら、最初のエラーに対処すれば、その後のエラーが直ってしまうことも多々あるからです。このようなことは、カッコの抜けによるエラーでよく起こります。次はエラーの例です。 - parse error before 'hoge'. 'hoge' の直前で文法解析に失敗しました。 直前の行末に ";" が抜けていることが多いです。 - Device or resource busy 文法上の問題ではありません。a.exe のプログラムがまだ(バックグラウンドで)動いていて、gcc が同じ名前のファイルを出力できないだけです。Ctrl-C を押して止めたつもりが、間違って Ctrl-Z を押してしまってるのでしょう。 -- 'fg' コマンドを実行して、バックグラウンドで動いているプロセスを呼び起こします。呼び起こしたプロセスは、Ctrl-C などで終了します。これを繰り返して、'fg' コマンドの出力が「no such job」になれば正常です。'gcc' でコンパイルしなおします。 文法上の問題ではありません。a.exe のプログラムがまだ(バックグラウンドで)動いていて、gcc が同じ名前のファイルを出力できないだけです。Ctrl-C を押して止めたつもりが、間違って Ctrl-Z を押してしまってるのでしょう。このような場合は、次のように操作します。 -- 'fg' コマンドを実行して、バックグラウンドで動いているプロセスを呼び起こします。そして、呼び起こしたプロセスを Ctrl-C などで終了させます。これを繰り返して、'fg' コマンドの出力が「no such job」になれば正常です。'gcc' でコンパイルできるようになります。 -- タスクマネージャで a.exe のプロセスを終了しても構いません。 -- よくわからなければ、ログオフしてログオンしなおせば、解消するはずです。 *** リンク時のエラー [#h022179e] gcc コマンドを実行した時に出るエラーという意味では、コンパイル時のエラーと同じですが、文法上のエラーではないので、メッセージががらっと変わって「何行目に間違いがあるか」がわからなくなってしまいます。 - undefined reference to `__hoge` 実体のない関数を呼び出しています。多くの場合は関数名のタイプミスでしょう。エディタに戻って 'hoge' を文字列検索するか、gcc に -g オプションを付けてコンパイルしなおして該当箇所の行番号を表示させます。(メッセージにあるアンダースコア (_) 2個は無視します。) もし分割コンパイルしているのであれば、リンクすべき *.o を間違えているのかもしれません。 > 数学関数を用いているのであれば gcc に "-lm" オプションが抜けていることも原因の1つではありましたが、いつの頃からか Cygwin の gcc には付けなくてもよくなっています。 > hoge() を呼び出しているのに '__hoge' とアンダースコア (_) が2個余分に表示される理由は、gcc の内部処理の都合なのでしょう。 > hoge() を呼び出しているのに '__hoge' とアンダースコア (_) が2個余分に表示される理由は、gcc の内部処理の都合だと想像されます。 - undefined reference to `_WinMain@16` main() 関数がありません。 もし分割コンパイルしているのであれば、gcc コマンドに *.o を出力させるためのオプション -c を付け加えます。 > 紛らわしいことに、メッセージと本当に足りないもの(=main()関数)が食い違っています。なぜこうなるのかというと、Cygwin の gcc は、main() がなければ自前で持ってる main() を使い、そこから WinMain() 呼び出しているため、なのだそうです。→http://soudan1.biglobe.ne.jp/qa3895829.html > 紛らわしいことに、メッセージ(=WinMain()関数)と本当に足りないもの(=main()関数)が食い違っています。なぜこうなるのかというと、Cygwin の gcc は、main() がなければ自前で持ってる main() を使い、そこから WinMain() 呼び出しているため、なのだそうです。→http://soudan1.biglobe.ne.jp/qa3895829.html *** 実行時のエラー [#j761bddf] 実行時にいくらエラーメッセージが表示されても、残念ながら手がかりになる情報はほとんど読み取ることができません。原因としては、配列の添え字あふれや、0 での割り算のようなものが考えられますが、ソースコード上の場所がわからないので、どこを疑ってよいのか見当がつきません。 > 実行された様子を確認するために、printf() で変数を表示をさせてみるのも1つの方法です。→[[Cygwinでデバッグ/不可解な動作]] //core を吐かせるには //http://www.sixnine.net/cygwin/cygwin-doc/smalltips.html ここでは、デバッガというツールを用いて、エラーの出ている場所の特定を行ってみます。まず、コンパイルの時に、オプションを余分につけておきます。 gcc -Wall -g hoge.c > この時点で警告が出た場合は→[[Cygwinでデバッグ/不可解な動作]]へ。 > オプション -g が重要です。デバッグ情報を埋め込みます。動作には影響ありませんので、常につけておいても害はありません。 > 最適化オプション -O ははずしておく(あるいは -O0(オーゼロ) を指定する)のが無難なようです。 次に、デバッガの中でプログラムを実行してみます。 gdb a.exe デバッガの中ではプロンプトが変化して (gdb) のようになります。「ここで入力できるのは gdb のコマンドですよ」という目印です。 エラーで止まってしまうプログラムを解析するのであれば、だいたい次のようなコマンドを順に入力します。 run プログラムを実行(エラーで止まるはず) where 現在実行中の場所を表示 list ソースコード表示 print i 変数 i の値を表示 quit 終了 他にも、多くの機能があります。ブレークポイントというのは、そこを実行した時に、一時中断する場所のことです。あやしそうな処理の直前にしかけておいて、変数の値を確かめながらゆっくりステップ実行するのに使います。 ブレークポイントを登録 break 行番号 break 関数名 break ファイル名:行番号 step ステップ実行(呼び出した関数の中も追いかける) next ステップ実行(呼び出した関数の中は追いかけない) finish 現在の関数の最後まで実行 continue 実行の継続 backtrace 関数の呼び出し関係を表示 display i 変数 i を常に表示 help ヘルプメッセージを表示 ただ単に Enter を入力すると、直前のコマンドが繰り返して実行されます。またコマンドは先頭1〜2文字の省略形でも入力できます。高度な利用法は他の文献を参照してもらうことにして、エラーで止まる場所が特定できるだけでも役立つと思うので、活用してみて下さい。 - http://uguisu.skr.jp/Windows/gdb.html - http://www-ise3.ise.eng.osaka-u.ac.jp/miura/programLecture/lecture5.html - http://rat.cis.k.hosei.ac.jp/article/devel/debugongccgdb1.html - http://rat.cis.k.hosei.ac.jp/article/devel/debugongccgdb2.html - http://rat.cis.k.hosei.ac.jp/article/devel/debugongccgdb3.html