C言語でのエラーハンドリング
Cだとファイルの操作は以下のようにできます。
FILE *fp = fopen(filepath, "r");
if(fp == NULL){
// エラーハンドリング
}else{
// ファイルを開いてなんか処理する
fclose(fp);
}
fopenは失敗したときにNULLを返しますが、
これだけですと何故失敗したのかを判断できません。
この問題は、失敗時に-1やNULLを返すシステムコールや関数では常に起きうる問題です。
このような問題が起きた場合には、errnoを利用することでエラーの種類を特定できる場合があります。
#エラーを判断するerrno
errnoは内でグローバルに定義された整数値です。
errno.h内にはエラーに対応した定数が定義されており、
エラーが起きた場合にerrnoに値を設定するシステムコールや関数があります。
何かしらの処理に失敗した場合にはこの値を確認することで、
エラーの種類を特定できる場合があります。
このとき、errnoはどのような場合も0に変わることはない為、
処理の前にerrnoに0を代入することで、
その処理のエラーかどうかを判断できます。
(正常終了した場合は前の値を保持し、またerrnoを設定しないものもあるため、
事前に0を入れないと該当の処理で書き換わったか判断できません)
また、引数にエラー番号を渡すと対応するエラー内容を、
標準出力に出力するperror、
文字列で返すstrerror
が存在します。
なお、errnoは一つしか無いため常に書き換えられる可能性があります。
そのため、エラーの特定や処理をする前に変数にコピーしておくことをオススメします。
具体的な使い方は次のコードを参考にしてください。
使い方
コード
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/time.h>
#include <sys/resource.h>
int main()
{
int number;
// 2: No such file or directory
FILE *fp = fopen( "no_exist_filepath", "r" );
number = errno;
if(fp == NULL){
perror("print error string by perror ");
printf("print error string by strerror: %s\n", strerror(number));
printf("print error code: %d\n", number);
}else{
fclose(fp);
}
// 22: invalid argument
errno = 0;
int ret = getpriority(10000000, 1000000);
number = errno;
if(ret == -1){
printf("\n");
perror("print error string by perror ");
printf("print error string by strerror: %s\n", strerror(number));
printf("print error code: %d\n", number);
printf("print return code: %d\n", ret);
}
return 0;
}
結果
print error string by perror : No such file or directory
print error string by strerror: No such file or directory
print error code: 2
print error string by perror : Invalid argument
print error string by strerror: Invalid argument
print error code: 22
print return code: -1