buf
がmalloc()
で割り当てられた文字バッファーの場合、free(buf)
はerrno
を設定/リセットしますか?
バッファが不要になったため、バッファをファイルに書き込んでから解放するとします。
コードのエラーポリシーがエラー時に-1を返すことであるとしましょう。
これは、メモリをリークすることなくバッファとエラーチェックを書き出す適切な方法ですか?
fputs(buf, somefile);
free(buf);
if (errno) return -1;
または、次のようにerrnoを自由に設定することを検討する必要がありますか...
fputs(buf, somefile);
if (errno){
free(buf);
return -1;
}
free(buf);
または、恐怖の恐怖、
do {
fputs(buf, somefile);
int save_errno = errno;
free(buf);
errno = save_errno;
if (errno) return -1;
} while(0);
ブロックを使用すると、これを再利用する必要がある場合に、ローカルのsave_errnoをさまざまな場所に存在させることができます。
これはすべて、free()がerrnoを設定するかどうかに依存するようです。
free()のLinuxマニュアルページ は、malloc()
などのマニュアルページでもあります。malloc()
設定のerrnoについて言及していますが、free()
については言及していません。
動的メモリを解放するためのGNU Cライブラリのマニュアルページ は、free()がerrnoを設定するかどうかについて言及していません。
そこで、free()がerrnoをリセットするかどうかを確認できるように、書き込みエラーを強制する短いプログラムを作成しましたが、そうではありません。この結果と、free()は非常に重要なので「もちろんerrnoを設定しない」という事実に頼るべきかどうか疑問に思っています。
# See if free() resets errno on a bad write
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
char * buf = malloc(256);
snprintf(buf,256,"%s\n", "Hello, World!");
FILE *badfile;
badfile = fopen("/dev/null","r");
fputs(buf, badfile);
free(buf);
printf("%d\n", errno);
printf("%s\n", strerror(errno));
}
POSIXは free
を定義してerrno
を設定しません(POSIXは現在禁止していないため、実装で禁止されている場合があります- @を参照してくださいArjunShankarの答え 詳細)。しかし、それはあなたの懸念にはあまり関係がありません。
エラーをチェックする方法が正しくありません。 fputs
の戻り値を確認し、0
より小さいかどうかを確認してください。そうである場合は、errno
をチェックして、失敗の原因を突き止めることができますが、これはオプションです(さらに関数を呼び出す前に行う必要があります)。
だから、このようなものがうまくいくはずです:
int result = fputs(buf, somefile);
/* optionally read errno here if result < 0 (before the free call) */
free(buf);
return (result < 0) ? -1 : 0;
POSIX準拠のfree
はerrno
todayを設定する可能性がありますが、将来的にはより良いものに変更される予定です。詳細:
errno
の定義は次のように述べています。このボリュームのPOSIX.1-2008の関数は、errnoを0に設定しません。関数の呼び出しが成功した後のerrnoの設定は、その関数の説明でerrnoを変更しないことを指定していない限り、指定されていません。
free
の定義自体は、free
がerrno
で何をするかを指定していません。これは、準拠しているfree
実装がerrno
を0にリセットしないことを意味します。ただし、ゼロ以外の値に設定する場合としない場合があります。
ただし、仕様の第8号(進行中の作業)は free
が設定されないことを具体的に保証するためにerrno
が必要です =有効な入力が渡されたとき
glibc は、この新しい要件に準拠するためにすでに準備を進めています。
C標準のerrno
の説明では、free
について何も言われていません。したがって、この機能に依存することはできません。
C標準によると(7.5エラー<errno.h>
)
3 ...この国際規格の関数の説明にerrnoの使用が記載されていない限り、エラーの有無にかかわらず、ライブラリ関数呼び出しによってerrnoの値がゼロ以外に設定されることがあります。
また、errno
の使用については、すでに述べたように、C標準のfree
の説明には記載されていません。
参照が失敗時に関数がerrno
でエラーコードを返すと言っていない場合、それはしません。
errno
をエラーコードに設定する関数は、(ほとんどの場合)errno
に現在のエラーコードが含まれることを別の方法で通知します。メモリ割り当て関数はNULL
を返し、他の多くの関数はゼロまたは負の数など。
このような関数は、成功した場合でもerrno
を変更する必要はなく、通常は変更されません。
通常、errno
を検査して、問題が発生したかどうかを判断することはできません。エラーが発生したことがわかった場合にのみ、より多くの情報を取得するためのものです。
最終規則の1つの例外はstrto{l, d, ul}
ファミリですが、最初の段落はそれらにも当てはまります。
また、失敗した場合を除いて、必ずしもerrno
を設定する必要はないため、最初にクリアする必要があります。そうしないと、古いエラーコードが含まれる可能性があります。