失敗の可能性がかなり高い、小さくて特定のタスクを実行する関数があるとしましょう。何かがうまくいかないことに対処するための最良の方法は何ですか?(私が問題が何であるかを知っていると仮定します)。
たとえば、2バイトの文字列を読み取って返す関数があるとします。
#include <stdio.h>
#include <stdlib.h>
char *bar(void)
{
char *foo = malloc(3);
scanf("%2s", foo);
return foo;
}
int main(void)
{
char *foo = bar();
puts(foo);
free(foo);
return 0;
}
上記の例では、エラー処理はまったくありません。ある種のエラー処理を実装する方法は2つありますが、どちらがより好ましいか、またはベストプラクティスと見なされるかはわかりません。
方法1(関数内からstderrにエラーメッセージを出力する):
#include <stdio.h>
#include <stdlib.h>
char *bar(void)
{
char *foo;
if(!(foo = malloc(3)))
{
fputs("\nError! Memory allocation failed.", stderr);
return 0x00;
}
scanf("%2s", foo);
return foo;
}
int main(void)
{
char *foo;
if(!(foo = bar())) return 1;
puts(foo);
free(foo);
return 0;
}
方法2(呼び出し元の関数からstderrにエラーメッセージを出力する):
#include <stdio.h>
#include <stdlib.h>
char *bar(void)
{
char *foo;
if(!(foo = malloc(3))) return 0x00;
scanf("%2s", foo);
return foo;
}
int main(void)
{
char *foo;
if(!(foo = bar()))
{
fputs("\nError! Memory allocation failed.", stderr);
return 1;
}
puts(foo);
free(foo);
return 0;
}
方法2が最善の方法だとほぼ考えています。そうすれば、その時点でその関数を何に呼んでいるかに応じて、エラーメッセージをより具体的にすることができるからです。方法2で私が心配しているのは、関数に複数の潜在的な障害点がある場合、関数で特に問題が発生したものを印刷する機能が失われるという事実です。
擬似コード:
IF FAILUREA
PRINT "FAILUREA OCCURED"
RETURN
IF FAILUREB
PRINT "FAILUREB OCCURED"
RETURN
私が呼び出していた関数が原因である場合、これはそれほど問題にはなりません。問題が発生したint
ことに基づいて、異なる整数値を返すことができるからです。しかし、Iの場合、char*
私は通常NULL
、失敗時に復帰しようとします(したがって、両方FAILUREA
とFAILUREB
が復帰しNULL
ます)。関数が失敗した原因を知る方法はありません。
だから私の質問は、エラーメッセージの処理に関してベストプラクティスは何ですか?