のglibc 実装でvfscanf()
次のコードを見つけることができます(執筆時点では、リンクされたファイルの 589 ~ 607 行目) の実装がscanf()
呼び出します。
if (skip_space || (fc != L_('[') && fc != L_('c')
&& fc != L_('C') && fc != L_('n')))
{
/* Eat whitespace. */
int save_errno = errno;
__set_errno (0);
do
/* We add the additional test for EOF here since otherwise
inchar will restore the old errno value which might be
EINTR but does not indicate an interrupt since nothing
was read at this time. */
if (__builtin_expect ((c == EOF || inchar () == EOF)
&& errno == EINTR, 0))
input_error ();
while (ISSPACE (c));
__set_errno (save_errno);
ungetc (c, s);
skip_space = 0;
}
input_error()
は#define
次のとおりです。
#define input_error() do {
errval = 1;
if (done == 0) done = EOF;
goto errout;
} while (0)
errout
末尾のクリーンアップ コードのラベルはどこにありますか。
そのため、呼び出しの前にerrno
が設定されているように見え、古い値は後で置き換えられ、変更されません。しかし、エラーが発生してそのステートメントが実行された場合 (特に、 if がに評価され、この場合はこれが発生しています)、元の値にリセットするコードがスキップされている可能性があります。そうは言っても、条件が真になるのはゼロではない場合のみであり、ここではそうではないようです。したがって、このコードとは関係がないかもしれませんが、これは私が設定されているのを見ることができる唯一の場所ですに。コメントが示唆するように、それ自体が をいじり、 に設定できます。これは に初期化されます0
inchar()
errno
if
inchar()
EOF
errno
errno == EINTR
errno
0
inchar()
errno
errno
inchar_errno
0
inchar_errno
223行目なので、更新されていないが割り当てられる他の実行パスがある可能性もありerrno
ます。