Considering fopen()
fails, in the following piece of code:
FILE *fp = fopen("file.txt", "w");
if (fp == NULL) {
printf("Error occurred while opening file, errno=%d, %s\n",
errno, strerror(errno));
exit(1);
}
Since the order in which function arguments are evaluated is unspecified in C, while invoking printf()
, in case call to strerror()
is evaluated (invoked) first and it fails, wouldn't errno
be set to something else when the line actually gets printed? Or, is it that errno
would have been copied into the activation record of printf()
even before evaluating strerror()
and hence would remain unchanged? Is this unspecified behaviour?
EDIT: Yes, I do understand that I can save errno
to some int
right after fopen()
, but that's not my point here. I am trying to figure out how the above piece of code behaves.
Since no return value is reserved to indicate an error, an application wishing to check for error situations should set errno to 0, then call strerror(), then check errno.
From the same article that you used. Very likely it's unspecified behaviour. MAN tells the same
POSIX.1-2001 and POSIX.1-2008 require that a successful call to strerror() or strerror_l() shall leave errno unchanged, and note that, since no function return value is reserved to indicate an error, an application that wishes to check for errors should initialize errno to zero before the call, and then check errno after the call.
So you can save errno
of fopen
, and then get errno
of strerror
. Or simply use perror
.
Considering
fopen
fails, in the following piece of code:FILE *fp = fopen("file.txt", "w"); if (fp == NULL) { printf("Error occurred while opening file, errno=%d, %s\n", errno, strerror(errno)); exit(1); }
Since the order in which function arguments are evaluated is unspecified in C, while invoking
printf
, in case call tostrerror
is evaluated (invoked) first and it fails, wouldn'terrno
be set to something else when the line actually gets printed?
That is indeed possible. Additionally, according to the C standard, errno
could be set to a nonzero value whether or not there is an error in the call to strerror
or any other library function provided the use of errno
is not documented for the function (see C17 7.5/3). However, POSIX (since POSIX.1-2001, and prior to that in 1997's Single UNIX Specification, version 2) guarantees that strerror
will not change the setting of errno
if successful.
Or, is it that
errno
would have been copied into the activation record ofprintf
even before evaluatingstrerrno()
and hence would remain unchanged? Is this unspecified behaviour?
It is unspecified behaviour. The arguments and function designator can be evaluated in any order (but there is a sequence point before the actual call to the function to avoid evaluations within a function body being interleaved with evaluations within another function body) (see C17 6.5.2.2/10).
This is an issue that could occur under Linux as the manual of strerror()
says in the NOTES section that errno
can be modified by the service:
POSIX.1-2001 permits strerror() to set errno if the call encounters an error, but does not specify what value should be returned as the function result in the event of an error. On some systems, strerror() returns NULL if the error number is unknown. On other systems, strerror() returns a string something like "Error nnn occurred" and sets errno to EINVAL if the error number is unknown. C99 and POSIX.1-2008 require the return value to be non-NULL.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.