理系学生日記

おまえはいつまで学生気分なのか

advanced linux programming

これ。
ISBN:978-0735710436:detail

assert

アプリケーションのコーディングにおける目標は、異常発生時にできるだけ早くプログラムを終了させるようにすること。というわけで、積極的に assert を使うべき。assert の果たす役割は、ランタイムチェックはもちろんのこと、プログラムのドキュメンテーションでもある。

NDEBUG オプションをコンパイラに与えることにより、プリプロセッサの段階で assert は除去される。そのため、assert の引数として副作用のある式を書いてはならない。また、ユーザは暗号めいた assertion を目にすることを望んでもいないので、ユーザ入力のバリデーションに assert を使うべきではない。

システムコールの失敗

プログラマはシステムコールを呼びだすことで、正しい結果や副作用が生じることを期待する。しかし、それらが必ずしも成功するとは限らないため、「成功したときに何が起こるか」だけでなく、「失敗したときに何が起こるか」を理解しておかなければならない。

多くのシステムコールは、リターンコードによりその成功・失敗を呼び出し元へ返却するが、その情報のみでは、リカバリに必ずしも十分ではない。そのため、多くのシステムコールはその失敗時に、errno 変数 *1 に値をセットする。全システムコールがこの変数を使用するため、システムコール失敗時は迅速にその値を他の変数へとコピーしておく必要がある。GNU/Linux では、これらの errno が何を意味しているのかを取得するために、strerror、perror を用意している。strerror は errno の意味しているところを示す文字列を返し、perror は errno が意味する文字列を stderr へと出力する。

システムコールでエラーが発生した場合、そのシステムコールを呼び出していた関数またはメソッドは、エラーが発生したことを呼び出し元に返す必要がある。ただし、単純にその場で return するのではなく、そのシステムコールが呼び出されるまでに確保したリソース、メモリ、開いたファイルなどは、きちんと解放しておかなければ、リークを生じる。

*1:厳密にはマクロ