Home > Software design >  Regarding errno and strerror()
Regarding errno and strerror()

Time:07-30

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 strerrno() 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.

CodePudding user response:

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.

CodePudding user response:

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?

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 of printf even before evaluating strerrno() 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).

  • Related