デバッグの工夫

Similar documents
DVIOUT

Cプログラミング1(再) 第2回

C プログラミング演習 1( 再 ) 2 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ

memo

Microsoft Word - Cプログラミング演習(12)

memo

gengo1-12

PowerPoint Presentation

memo

gengo1-12

slide5.pptx

PowerPoint プレゼンテーション

ファイル入出力

Microsoft Word - no11.docx

memo

ファイル入出力

Microsoft PowerPoint - bp02.ppt

Microsoft PowerPoint - kougi4.ppt

02: 変数と標準入出力

Microsoft PowerPoint - prog06.ppt

Microsoft PowerPoint - kougi9.ppt

Microsoft PowerPoint - kougi11.ppt

Microsoft Word - no15.docx

Taro-ファイル処理(公開版).jtd

PowerPoint プレゼンテーション

プログラミング基礎

memo

全体ロードマップ インターネット電話 音の符号化 ( 信号処理 ) 今日 音の録音 再生 ネットワーク ( ソケット ) プログラミング ファイル入出力 インターネットの基礎 C プログラミング基礎

プログラミング実習I

C言語入門

コマンドラインから受け取った文字列の大文字と小文字を変換するプログラムを作成せよ 入力は 1 バイトの表示文字とし アルファベット文字以外は変換しない 1. #include <stdio.h> 2. #include <ctype.h> /*troupper,islower,isupper,tol

PowerPoint Presentation

Microsoft PowerPoint - kougi2.ppt

memo

PowerPoint プレゼンテーション

第1回 プログラミング演習3 センサーアプリケーション

Microsoft PowerPoint pptx

Microsoft PowerPoint - kougi6.ppt

B演習(言語処理系演習)第一回

PowerPoint プレゼンテーション

テキスト処理第 2 回 田中哲産業技術総合研究所情報技術研究部門 akira/textprocess/

関数の呼び出し ( 選択ソート ) 選択ソートのプログラム (findminvalue, findandreplace ができているとする ) #include <stdiu.h> #define InFile "data.txt" #define OutFile "surted.txt" #def

kiso2-03.key

2006年10月5日(木)実施

Microsoft Word - Training10_プリプロセッサ.docx

02: 変数と標準入出力

Microsoft PowerPoint - 計算機言語 第7回.ppt

gengo1-12

Prog1_12th

プログラミング演習3 - Cプログラミング -

演算増幅器

情報処理演習 B8クラス

Prog1_6th

PowerPoint プレゼンテーション

02: 変数と標準入出力

Microsoft PowerPoint - adi05.ppt [互換モード]

関数の呼び出し ( 選択ソート ) 選択ソートのプログラム (findminvalue, findandreplace ができているとする ) #include <stdio.h> #define InFile "data.txt" #define OutFile "sorted.txt" #def

#include<math.h> 数学関係の関数群で sin() cos() tan() などの三角関数や累乗の pow() 平方根を求める sqrt() 対数 log() などがあります #include<string.h> 文字列を扱う関数群 コイツもまた後日に 4. 自作関数 実は 関数は自分

Microsoft PowerPoint - kougi7.ppt

<4D F736F F D2091E63589F182628CBE8CEA8D758DC08E9197BF2E646F6378>

Microsoft Word - no13.docx

今までの復習 プログラムで最低限必要なもの 入力 ( キーボードから ファイルから ) 出力 ( 画面へ ファイルへ ) 条件分岐 : 条件の成立 不成立により 異なる動作をする 繰り返し : 一定の回数の繰返し 条件成立の間の繰返し 関数の定義 関数の呼び出し C ではそれ以外に ポインタ データ

数はファイル内のどの関数からでも参照できるので便利ではありますが 変数の衝突が起こったり ファイル内のどこで値が書き換えられたかわかりづらくなったりなどの欠点があります 複数の関数で変数を共有する時は出来るだけ引数を使うようにし グローバル変数は プログラムの全体の状態を表すものなど最低限のものに留

02: 変数と標準入出力

プログラミング及び演習 第1回 講義概容・実行制御

RX ファミリ用 C/C++ コンパイラ V.1.00 Release 02 ご使用上のお願い RX ファミリ用 C/C++ コンパイラの使用上の注意事項 4 件を連絡します #pragma option 使用時の 1 または 2 バイトの整数型の関数戻り値に関する注意事項 (RXC#012) 共用

基礎プログラミング2015

基礎プログラミング2015

Microsoft PowerPoint - kougi8.ppt

DVIOUT

新・明解C言語 実践編

PowerPoint プレゼンテーション

AquesTalk プログラミングガイド

memo

r07.dvi

Microsoft PowerPoint - å®�æ−•è©¦é¨fi3ㆮ対ç�Œ.pptx

ohp07.dvi

Microsoft PowerPoint - prog07.ppt

Microsoft PowerPoint - prog04.ppt

C言語講座

メソッドのまとめ

02: 変数と標準入出力

PowerPoint プレゼンテーション

£Ã¥×¥í¥°¥é¥ß¥ó¥°ÆþÌç (2018) - Â裱£²²ó ¡Ý½ÉÂꣲ¤Î²òÀ⡤±é½¬£²¡Ý

プログラミング演習3 - Cプログラミング -

Microsoft Word - no12.doc

Visual Studio 2012 インストールマニュアル

A/B (2018/10/19) Ver kurino/2018/soft/soft.html A/B

た場合クラスを用いて 以下のように書くことが出来る ( 教科書 p.270) プログラム例 2( ソースファイル名 :Chap08/AccountTester.java) // 銀行口座クラスとそれをテストするクラス第 1 版 // 銀行口座クラス class Account String name

関数 C 言語は関数の言語 関数とは 関数の定義 : f(x) = x * x ; 使うときは : y = f(x) 戻り値 引数

書式に示すように表示したい文字列をダブルクォーテーション (") の間に書けば良い ダブルクォーテーションで囲まれた文字列は 文字列リテラル と呼ばれる プログラム中では以下のように用いる プログラム例 1 printf(" 情報処理基礎 "); printf("c 言語の練習 "); printf

Prog1_15th

Microsoft PowerPoint - exp2-02_intro.ppt [互換モード]

AquesTalk Win Manual

プログラミング基礎

1 1.1 C 2 1 double a[ ][ ]; 1 3x x3 ( ) malloc() 2 double *a[ ]; double 1 malloc() dou

Microsoft PowerPoint - 09.pptx

Microsoft PowerPoint - CproNt02.ppt [互換モード]

Microsoft Word - Cプログラミング演習(9)

新版明解C言語 実践編

Transcription:

バグを減らす デバッグの工夫 ~ プログラミング実習で生き残るために ~ 2013/02/12 金森由博

よくあるプログラミングの風景 課題めんどくさい とりあえず適当に書くか エラーチェック めんどくさい あとまわし ちゃんと動くかわかんないけど全部書いちゃお ふー やっと全部書けた コンパイルしよ!? エラーメッセージの意味がわからん!! はぁ やっとコンパイルが通った 実行しよ えっ!? なんでセグメンテーション違反!? 何時間かけても動かない もうやだ

よくあるプログラミングの風景で 一番時間がかかるのはデバッグ

なんでそんなに時間がかかった?

ポインタ 構造体にまだ慣れてない 復習 & 練習するしかない

よくあるプログラミングの風景 課題めんどくさい とりあえず適当に書くか エラーチェックしていない 方針をちゃんと決めていない エラーチェック めんどくさい あとまわし ちゃんと動くかわかんないけど全部書いちゃお ふー やっと全部書けた コンパイルしよ!? エラーメッセージの意味がわからん!! はぁ やっとコンパイルが通った 実行しよ えっ!? なんでセグメンテーション違反!? 問題の原因を絞れていない 部分ごとにテストしていない 何時間かけても動かない もうやだ

バグを減らす デバッグの工夫 プログラミングの前に 紙に方針を書いて練る 方針によってはバグが出にくくすることも可能 バグを入れない工夫をする エラーチェック & エラーメッセージを丁寧に 全部書いてから ではなく 少し書いたらテスト バグが出たら 原因の箇所を素早く特定する コメントアウトなどでバグの箇所を絞る

エラーチェックとエラーメッセージ エラーが起こるかもしれないところはちゃんとチェックする エラーメッセージは一目見てわかるように 将来デバッグをしているときの自分は きっと頭が疲れている 将来の自分に優しくする 単に a とか error とか不親切なものではなくどんなエラーが起きたか詳しく書く

例 : コマンドライン引数 チェックなし 最悪 int main(int argc, char *argv[]) { int n = atoi(argv[1]); : コマンドライン引数が間違っているといきなりクラッシュ 実行した人は困惑

例 : コマンドライン引数 エラーメッセージあり さっきよりはまし int main(int argc, char *argv[]) { int n; if (argc!= 2) { printf( おばあちゃん頭だいじょうぶ?(^ω^) n ); return -1; } : が どんなエラーなのかわからない しかもイラッとする

例 : コマンドライン引数 丁寧なエラーメッセージ int main(int argc, char *argv[]) { int n; if (argc!= 2) { printf( エラー : 整数の引数が 1 つ必要です n ); return -1; } : 何が間違っていたのか一目でわかる

例 : ファイルのオープン エラーチェックだけ エラーメッセージなし int LoadImage(const char *filename, ) { FILE *fp; if ( (fp = fopen(filename, rb )) == NULL ) return 0; : エラーメッセージがないので プログラムの実行中に何が起きたかわからない

例 : ファイルのオープン エラーメッセージあり int LoadImage(const char *filename, ) { FILE *fp; if ( (fp = fopen(filename, rb )) == NULL ) { printf( Cannot open file n ); return 0; } : しかしまだ改善の余地あり

例 : ファイルのオープン どの関数で どのファイルを 開けなかったか int LoadImage(const char *filename, ) { FILE *fp; if ( (fp = fopen(filename, rb )) == NULL ) { printf( %s: cannot open %s n, FUNCTION, filename); return 0; } バグの原因を特定しやすい :

少し書いたらテスト 全部書いてからテストしようとすると ミスが重なって原因の特定が難しくなる 特に ヘッダファイルのインクルード忘れ や 括弧 { ( の閉じ忘れ などは謎のエラーが出やすい プログラムを部品 ( モジュール = 関数 ) に分け部品を作るごとに正しく動くかテストする キーワード : 単体テスト テスト駆動開発 IT 企業での開発でも実際に行われている

少し書いたらテスト いきなり全部書かない int main(int argc, char *argv[]) { /* スペースの都合でチェック略 */ Matrix A; Vector b; LoadLinearSystem(argv[1], &A, &b); printf( Matrix A: ); FprintMatrix(&A); printf( Vector b: ); FprintVector(&b); SolveGaussJordan(&A, &b); printf( Vector x: ); FprintVector(&b); } return 0;

少し書いたらテスト 例えば int main(int argc, char *argv[]) { /* スペースの都合でチェック略 */ Matrix A; Vector b; LoadLinearSystem(argv[1], &A, &b); /* これだけテスト */ return 0; } int LoadLinearSystem( ) { /* 何か処理を行う */ /* 期待する結果になったかテスト printf などで値を確認 */ return 1; }

バグの箇所を絞る それでもバグが出たら バグの箇所を絞る int main(int argc, char *argv[]) { /* スペースの都合でチェック略 */ Matrix A; Vector b; LoadLinearSystem(argv[1], &A, &b); #if 0 /* 便利.1 にすればコンパイルされる. ネスト可 */ printf( Matrix A: ); FprintMatrix(&A); printf( Vector b: ); FprintVector(&b); SolveGaussJordan(&A, &b); : #endif ここだけ実行してテスト

バグの箇所を絞る それでもバグが出たら バグの箇所を絞る int main(int argc, char *argv[]) { /* スペースの都合でチェック略 */ Matrix A; Vector b; LoadLinearSystem(argv[1], &A, &b); printf( Matrix A: ); FprintMatrix(&A); #if 0 printf( Vector b: ); FprintVector(&b); 問題なければ次へ SolveGaussJordan(&A, &b); : #endif

バグの箇所を絞る for 文の中で変数の変化を調べる for (ri = 0; ri < A->rows; ri++) for (ci = 0; ci < A->cols; ci++) { /* 何か計算する */ printf( A(%d,%d) = %f n, ri, ci, A->elems[ci+ri*A->cols]); } できるだけ詳しく わかりやすく 引数に期待される値が入っているか調べる void FprintMatrix(Matrix *mat) { printf( FprintMatrix: rows = %d, cols = %d n, mat->rows, mat->cols); : } できるだけ詳しく わかりやすく

それでも詰まったら 得意な友達 TA さん 教員に質問 相談する プログラミングが得意な人は何が違う? バグの場所を特定する能力 に長けている 知識 経験の差 一人で延々と悩まないこと 他の人に頭を下げて教えを乞うことも大事