どのような原因で失敗したのかを教えてくれるerrnoについて解説する。errnoは、システムコールやライブラリ関数を利用し始めると大変お世話になる。エラーを示す値にセットされる。その原因を格納する先として利用される、errno自体はint型の整数としてアクセスできる。<errno.h>と、errno.hをインクルードすると参照できるようになる。スレッドローカルストレージとして定義されており、スレッドセーフにアクセス可能だ。その実体はスレッドごとに異なっているのだ。その値を参照するまでに、他のスレッドで発生したエラーによって上書きされたりはしない。そのような仕組みがなければ、複数のスレッドが動作し始めた時点で使いものにならないだろう。この辺の話がちんぷんかんぷんという場合も安心して欲しい。要するに、余計なことは考えずに使って問題ない。次に、実際errnoを参照するサンプルプログラムを動かしてみよう。失敗したらerrnoを表示、成功したら何もせず終了というシンプルな内容だ。errnoで検出しようとしている処理の直前で、errnoを0に初期化している。エラーが起こらなければerrnoの値は更新されない。そのため初期化しないと、それ以前に発生したエラーを拾ってしまう可能性があるからだ。その時はerrnoに何らかの値がセットされるためなくても問題はない。errnoの値を見ないと失敗したかどうかわからない、という関数もある。その場合は、errnoの初期化は必須となる。./errno13と、一応エラーが区別されているようだが、数字だけではちんぷんかんぷん。(POSIX.1)...と、エラーの定義リストがある。表示するためだけに、毎回これを調べたりというのはやってられない。表示のためにコード上で毎回比較したりというのをやるのは非効率すぎる。いうことで、当然というかその辺をフォローしてくれる関数も用意されている。strerrorを紹介する。directoryと、番号で表示されるよりも意味のわかるメッセージが得られた。実はstrerrorは、必ずしもスレッドセーフではない。その場合、strerrorの呼び出しのたびに同じ領域が上書きされてしまうからだ。マルチスレッドな環境で安全に利用したい場合はstrerror_rの方を利用する必要がある。複数のスレッドから同時にコールされても問題は起こらない。XSI準拠版と、GNU版で戻り値が違っているらしい。移植性を考えるなら、戻り値を無視して利用したほうが良さそうだ。マルチスレッド環境以外にも問題が発生する使い方がある。意図通りに動作せず、2つ同じ文字列が表示されてしまう場合があるので注意しよう。次は、perrorを紹介する。サンプルプログラムを以下のように書き換える。denied引数に指定した文字列に追加して、エラー文字列が表示されるという関数である。シンプルな記述で、いい感じのメッセージを表示してくれる。manによる定義は以下のようになっている。自前でコードを書く必要はない。内部ではstrerror_rが使われているので、スレッドセーフでもある。出力先は標準エラー出力となっている。単純にエラー出力をしたいというだけなら、この関数だけで事足りるだろう。付与できる文字列は固定で、この関数自体では書式指定などはできない。環境によっては、perrorの利用を禁止している場合もあるだろう。strerrorでエラーメッセージを表示する必要があるだろう。最後に、おまけとしてもう一つ、printfのglibc拡張書式を紹介する。おすすめできない方法であるが利用のしかたによっては便利だ。それ故、「おまけ」として紹介する。サンプルプログラムを以下のように書き換える。denied完全に、perrorの実行例と同じになる。単体でstrerror(errno)の結果を表示する。実装的にはちゃんとstrerror_rが使われているので、スレッドセーフに利用できる。その辺の心配も無用だ。出力フォーマットの自由度が高いという点があげられる。使ってしまうと移植性に問題が出てしまう。有益に利用できるだろう。いうわけで、エラーが発生した時のその原因を表示させる方法について解説した。開発中はこのような記述を面倒臭がらずにきちんと行うことで、デバッグがしやすくなるだろう。更新情報2018/07/28lsっぽいコマンドを作る13アップしました。2018/07/13lsっぽいコマンドを作る12アップしました。2017/01/04lsっぽいコマンドを作る11アップしました。2017/01/03lsっぽいコマンドを作る10アップしました。(https://commoncrawl.org/faq/)。