When fopen() fails

C

Christopher Benson-Manica

Sathyaish said:
If fopen fails, is there a way to know why?

If by "fails" you mean "returns NULL", yes. The global variable errno
(found in <errno.h>) contains information about what went wrong; you
can use perror() to print that information as a readable string.
 
B

Ben Pfaff

If fopen fails, is there a way to know why?

You can examine errno or look at the corresponding message
returned by strerror(). It's not guaranteed to work portably,
but reasonable implementations will provide a useful message.
 
D

Dave Vandervies

If by "fails" you mean "returns NULL", yes. The global variable errno
(found in <errno.h>) contains information about what went wrong; you
can use perror() to print that information as a readable string.

If I'm not mistaken, fopen isn't required to set errno if it fails.
(Though most implementations that attempt to provide nonzero QoI do
arrange for it to be set usefully.)


dave

--
Dave Vandervies (e-mail address removed)
Claiming that ANSI C does not allow a weird author at the keyboard is wrong.
Thanks for the clarification. For a moment there I was afraid I'd have to find
other work. --Ben Pfaff and Michael M Rubenstein in comp.lang.c
 
G

Gordon Burditt

If fopen fails, is there a way to know why?

errno might (*MIGHT*) tell you why. Or it might not. fopen() is
not guaranteed to set errno, but in my opinion it is worth presenting
the information to the user anyway. You can turn the errno code into
a supposedly-human-readable message with strerror() or perror().

#include <stdio.h>
#include <stdlib.h>

FILE *f;

f = fopen(name, "r");
if (f == NULL) {
perror(name);
exit(EXIT_FAILURE);
}

This code might give you a message like:

foo.txt: Permission denied
or
foo.txt: too many open files

or it might give you a message like:

foo.txt: Not a typewriter
or
foo.txt: Error 0

In creating error messages, it's a good idea to include WHAT failed,
on WHAT object, and WHY. The above examples don't say "opening for
read", and they really should, especially if the program may do
other things, like opening files for write or deleting them. If
the object is a file, include it's name (assuming it's available -
the name of stdout or stdin probably isn't). perror() or strerror()
will give you some idea of the WHY, sometimes.

Gordon L. Burditt
 
E

Eric Sosman

Christopher said:
If by "fails" you mean "returns NULL", yes. The global variable errno
(found in <errno.h>) contains information about what went wrong; you
can use perror() to print that information as a readable string.

FYI, this is true of many C implementations but it
is *not* required by the Standard. Some people think
that's a reason not to use perror() after fopen() fails:
the error message may have nothing at all to do with the
failure and could be misleading. Others (myself among
them) take the optimistic view that the error message
might be helpful, and are accustomed to treating all such
messages with just a little suspicion. Some go so far
as to decorate the message with a disclaimer:

FILE *fptr = fopen(filename, mode);
if (fptr == NULL) {
fprintf (stderr, "Failed to open %s\n"
"The reason *may* have been %s\n",
filename, strerror(errno));
...
}

Take your pick.
 
S

S.Tobias

Eric Sosman said:
FYI, this is true of many C implementations but it
is *not* required by the Standard. Some people think
[snip]

fread/fwrite are not required.
Same for fgetc/fputc/fgets/etc...
fsetpos/fgetpos are.
ftell is, but fseek is not.
Functions like fgetwc are required to set errno only
with specific value, but not otherwise. fgetws is not
required to set errno.

These are just a couple of examples. I wonder why we have to have
such a mess. Why couldn't the Standard require all functions that
interface with the system to always set errno, or to set it to
some EUNKNOWN value if error information is unavailable?
In some cases it's obvious the error information is available
and the function could set errno (eg. if ftell can set errno, I don't
see a reason why fseek couldn't; same for fgetwc/fgetws pair).

I tend to avoid perror() at all, if I don't really-really have to.
 
C

Christopher Benson-Manica

Eric Sosman said:
FYI, this is true of many C implementations but it
is *not* required by the Standard.

Whoops... thanks for the heads up.
 
D

Dan Pop

In said:
If by "fails" you mean "returns NULL", yes. The global variable errno
(found in <errno.h>) contains information about what went wrong; you
can use perror() to print that information as a readable string.

Yes, but you must be careful about it. The correct scenario is:
reset errno, call fopen, if it fails and errno is non-null you can assume
that its value provide a clue about the failure of fopen and translate it
into a meaningful message (perror or strerror), otherwise you must report
a failure for an unknown reason.

In the case of fopen, errno is the only mechanism provided by the C
language to help the programmer to generate meaningful error messages that
could help the user to understand and correct the problem. It is a shame
that the C standard doesn't require it to work.

Dan
 
P

pete

Dave said:
Shouldn't that be "nonzero"? ('Ts an integer value and not a pointer,
after all...)

"null" just means "zero".
"null pointer" is a pointer, "null character" is an integer.
 
R

Richard Bos

pete said:
"null" just means "zero".

Null is more general than "zero", because...
"null pointer" is a pointer,

....exactly. A null pointer need not be zero in any way (as opposed to a
null pointer _constant_).
"null character" is an integer.

But, depending on whether you mean '\0', or char a which happens to be
null, not necessarily an int.

Richard
 
D

Dan Pop

In said:
Shouldn't that be "nonzero"? ('Ts an integer value and not a pointer,
after all...)

Please elaborate on the semantic differences between "null" and "zero"
in the context of the value of errno.

Dan
 
P

pete

Richard said:
Null is more general than "zero", because...


...exactly. A null pointer need not be zero in any way
(as opposed to a null pointer _constant_).

A null pointer will compare equal to zero, that's one way.
But, depending on whether you mean '\0', or char a which happens to be
null, not necessarily an int.

I meant "integer", as in "integer type".
 
K

Keith Thompson

Please elaborate on the semantic differences between "null" and "zero"
in the context of the value of errno.

There are no semantic differences, but "zero" would be clearer. The
word "null" is commonly used to refer to certain pointer values (NULL)
and character values ((char)'\0'), but rarely used to refer to a zero
integer value. The phrase "errno is non-null" isn't incorrect, it's
just an odd way of putting it. It's really not a big deal.
 
S

S.Tobias

Dan Pop said:
Yes, but you must be careful about it. The correct scenario is:
reset errno, call fopen, if it fails and errno is non-null you can assume
that its value provide a clue about the failure of fopen and translate it
into a meaningful message (perror or strerror), otherwise you must report
a failure for an unknown reason.

I don't quite understand it. What is the purpose of setting errno to
zero before function call? If a function sets errno on error, it will
do so - doesn't matter what the previous value was.
 
R

Richard Tobin

S.Tobias said:
I don't quite understand it. What is the purpose of setting errno to
zero before function call? If a function sets errno on error, it will
do so - doesn't matter what the previous value was.

But functions doesn't clear errno on non-error, so you need to clear
it to be sure you are not seeing the some earlier (presumably
already-dealt-with) error.

-- Richard
 
J

Jonathan Adams

"S.Tobias said:
I don't quite understand it. What is the purpose of setting errno to
zero before function call? If a function sets errno on error, it will
do so - doesn't matter what the previous value was.

But fopen() is not required to set errno every time it returns NULL. So
there is no way to reliably differentiate "failed and set errno" and
"failed and did not set errno" without resetting errno before the call.

This is quite similar to the problem of reliably getting an error return
from strtoul().

Cheers,
- jonathan
 
S

S.Tobias

Jonathan Adams said:
But fopen() is not required to set errno every time it returns NULL.

Ah, thanks! I think I see what I was missing.

If a function does not communicate an error via errno, it is allowed
to set errno to any value it wants (except zero).
If a function communicates errors though errno, it is required either
to set errno to an error value, or to leave errno with the same value
as before the call.

Please correct me if that's not right.
 
E

Eric Sosman

S.Tobias said:
Ah, thanks! I think I see what I was missing.

If a function does not communicate an error via errno, it is allowed
to set errno to any value it wants (except zero).
If a function communicates errors though errno, it is required either
to set errno to an error value, or to leave errno with the same value
as before the call.

Please correct me if that's not right.

That's *almost* right. If an errno-setting function
succeeds, it may set errno to any non-zero value that it
pleases; it need not leave errno unchanged. When the
function returns its success indication it means "errno
is irrelevant," not "errno is undisturbed."

See Question 12.24 in the comp.lang.c Frequently Asked
Questions (FAQ) list

http://www.eskimo.com/~scs/C-faq/top.html
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

fopen 20
Working with files 1
fopen 17
fopen question 7
Problem with fopen 13
fopen() questions 17
HELP:function at c returning (null) 4
PHP failed to create file 13

Members online

Forum statistics

Threads
474,147
Messages
2,570,834
Members
47,382
Latest member
MichaleStr

Latest Threads

Top