--/--/--
スポンサーサイト
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
新しい記事を書く事で広告が消せます。
プログラミングやソフト開発に関するTIPSなど
2015/08/10
怪しげな新興宗教の大半は、「目を覚ませ」と怒鳴りながら、
信者たちの目を瞑ったままにさせようとする。『ラッシュライフ』 - 伊坂 幸太郎
2015/07/28
困難は分割せよ『方法序説』 - デカルト
2015/07/22
眺めているうちに、いろいろ気づいてくる
You can observe a lot just by watching.ジョセフ・マーフィー
$ sudo apt-get install minicom
$ sudo minicom --device /dev/ttyUSB0 minicom: cannot open /dev/ttyUSB0: No such file or directoryNo such file or directoryではなく、Permission deniedの場合もあるみたいです。
$ sudo adduser <ユーザー名> dialout
$ sudo vi /lib/udev/rules.d/50-udev-default.rules KERNEL=="tty[A-Z]*[0-9]|pppox[0-9]*|ircomm[0-9]*|noz[0-9]*|rfcomm[0-9]*", GROUP="dialout", MODE="0666"
$ sudo LANG=c minicom -s
$ vi ~/.bashrc alias minicom="mkdir -p ~/minilog ; LANG=C minicom -C ~/minilog/`date +%y%m%d_%H%M%S`.log"
2015/07/14
まかせてはいるけれども、たえず頭の中で気になっている。そこでときに報告を求め、問題がある場合には、適切な助言や指示をしていく。それが経営者のあるべき姿だと思います。これは言いかえますと“まかせてまかせず”ということになると思います。まかせてまかせずというのは、文字どおり“まかせた”のであって、決して放り出したのではないということです。
const char* month_name(int month) { const char* name[] = {"Jan", "Feb", "Mar", "Apl", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; if (month < 1 || month >= 12} return NULL; /* invalid month */ return name[month - 1]; }月を文字列に変換する関数ですが、1〜12以外はエラーとしてNULL(0)を返しています。
int print_date(int month, int day) { if (month < 1 || month >= 12} return -1; ..... printf("%s-%d\n", month_name(month), day); }先ほどと同じ範囲チェックがここでもされています。もし、month_name()がここでしか使われない、つまり、この関数の専用内部関数なのであれば、month_name()内の範囲チェックは冗長です。言い換えると、month_name()内のエラーチェックは内部のバグでもない限り発生することはありません。そもそも、print_date()では、month_name()でエラー、つまり、NULLがかえってくることを想定していないので、万が一NULLが返ってきたらNULL pointerアクセスでsegmentation fault等を引き起こします。
const char* month_name(int month) { const char* name[] = {"Jan", "Feb", "Mar", "Apl", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; assert(month > 0 && month < 12) return name[month - 1]; }こう書くことで、この関数は前提条件として、引数に1から12しかとらないということが表現されます。範囲チェックをさぼっているのではなく「上位にまかせている」ということがこれではっきりします。アサーションであれば、処理されないようなエラーを返すコードもないので、そもそも単体テストも必要ありません。万が一、上位関数のロジックが間違っていれば、assertにひっかけて早期検出も可能です。
int print_date(int month, int day) { if (month < 1 || month >= 12) { assert(0); return -1; } ..... printf("%s-%d\n", month_name(month), day); }エラー処理の中に、assert(0);が書かれており、どっちつかずになってしまっています。但し、この関数が通常外部関数で使われているものであり、デバッグ用にエラー発生次第abortするという機能として、コンパイルオプション等で有効無効が設定できるようなアサーションなのであれば、それはデバッグを効率化するひとつの方法だと思います。
.... ercd = loc_mtx(MTX1); /* lock mutex */ assert(ercd == E_OK); ....mutexの取得失敗をassertで確認しています。通常、mutexの取得はパラメータエラーや、同一タスクでの二重取得等の内部ロジックの不具合でしか起こらないことが多く、ここでエラーを返しても上位関数ではどうすることもできないので、このような場合は、アサーションが適当です。(失敗するはずはないという表明になる)
.... ercd = loc_mtx(MTX1); /* lock mutex */ if (ercd != E_OK) { printf("loc_mtx failed : %d\n", ercd); abort(); ....
2015/06/29
我々の犯す一つの大きな間違いは、原因を結果の間近にあると考えることにある。ゲーテ
2015/06/11
今は終わりではない。これは終わりの始まりですらない。しかしあるいは、始まりの終わりかもしれない。
a[-1] = 0;C言語では、配列int a[n]は、*((int*)(((int*)a + n))と等しいということなので、aが配列名、つまり、
int a[10]のように定義されたものなら、それは範囲外アクセスになってしまいます。
int b[10] int* a = &b[1];のようなものであれば、*(a-1) = b[0]なので、問題なく動作します。
int b[10] int* c = &b[-1];C言語的には、ポインター 演算は、一度に割り振られた領域と、仮想的な"終端"を越えた1つめ の要素にだけ定義されていて、それ以外では未定義になります。よって、aが有効なアドレス空間の先頭に位置していた場合などに、a[-1]が有効なアドレスになるとは限らないということがありえます。
#define ARRAY_SIZE 200 int my_array[ARRAY_SIZE]; int array(int n) { if (n >= ARRAY_SIZE) { return -1; } return my_array[n]; }
#define ARRAY_SIZE 200 int my_array[ARRAY_SIZE]; int array(int n) { if (n >= ARRAY_SIZE) { return -1; } return my_array[n]; } int func() { char n = 150; printf("%d\n", array(n)); }今後は、nがchar型になっています。char型は処理系によって、符号付きの場合と、符号なしの場合がありますが、符号ありの場合、150という値は保持されず、負の値になってしまいます。よって、負数を意図して使おうとしているわけではないものの、結果的に負数を使ってしまっています。
2015/05/01
落としたトーストがバターを塗った面を下にして着地する確率は、カーペットの値段に比例する
【関連記事】
・このバグ直しますか? - 原因療法と対症療法
・バグを潜伏させない工夫
・デバッグと不確定性原理
・デバッグ指向のススメ
【関連書籍】
2015/03/13
おまえ達のやっていることは検索で、思索ではない伊坂幸太郎 - 『魔王』より
【関連記事】
・WindowsでCUI環境
【関連書籍】
・ライフハッカー式整理のアイデア122―賢い人はなぜいつも机がきれいなのか? 小山 龍介
・デスクワークを3倍効率化するテクニック―エクセルの3つの機能で仕事のスピードを加速する 奥谷 隆一