C++ I/O error detection

R

Rennie deGraaf

If a C++ I/O operation fails, then how can I determine the cause? For
instance, in C, I'd do something like this:

FILE* file;
file = fopen("foo.txt", "r");
if (file == NULL)
{
switch(errno)
...
}

In C++, the best I can come up with is

istream in(foo.txt);
if (in.bad())
{
...
}
else if (in.fail())
{
...
}

However, this doesn't tell me why the error occurred; just that
something went wrong.

Also, bad() is supposed to be true on a fatal error, and fail() on a
non-fatal error. What are considered fatal and non-fatal errors?

Thanks,
Rennie
 
R

rajkumar

I am not sure if the standard mandates fopen indicate/set any
meaningfull error codes.

look up "errno" in ERRNO.H it might be the most portable solution.


Raj
 
R

Rennie deGraaf

I am not sure if the standard mandates fopen indicate/set any
meaningfull error codes.

look up "errno" in ERRNO.H it might be the most portable solution.

I know about errno for C I/O functions. I wanted to know how to get the
same information using the C++ I/O classes. Do they set errno, too?

Rennie
 
S

Stephen Howe

I know about errno for C I/O functions. I wanted to know how to get the
same information using the C++ I/O classes. Do they set errno, too?

They are under no obligation to do so.

Stephen Howe
 
D

Dietmar Kuehl

Rennie said:
I know about errno for C I/O functions.

I think his point is more: What useful requirements about the contents
of 'errno' does the C standard make? Hint: none. The only known error
which may be stored in 'errno' under some situations is 'EILSEQ'.
There are various places where an implementation defined value is set
in 'errno' but this does not really provide solid grounds for a
platform
independent error reporting strategy. Of course, for stdio other
standards, e.g. POSIX, cover some error cases, at least.
I wanted to know how to get the same information using the C++ I/O
classes. Do they set errno, too?

It depends on whom you ask :) If you asked me, I would say that the
C++ standard indeed mandates setting of 'errno' in certain cases! It
does not do so explicitly, though, but by reference: various function
in IOStreams are described to behave "as if" they called a C library
function. Of course, this includes setting 'errno' to the appropriate
value. Unfortunately, if you'd asked other implementers of the
standard IOStreams library, they disagree. The funny thing is that
most of these implementations still actually set 'errno'! This is
because the underlying system functions, e.g. POSIX's open(2), read(2),
write(2), etc. set 'errno' and nobody bothers to reset 'errno' after
these calls. That is, it is common behavior of the implementations
and arguably specified by the standard but most implementers actually
disagree that this is what the standard says although there is no
direct alternative in C++! If somebody would file a defect on this
issue ("reasons for errors not accessible for stream" or something
like this) we would at least get some clarification.
 
R

Rolf Magnus

Dietmar said:
I think his point is more: What useful requirements about the contents
of 'errno' does the C standard make? Hint: none. The only known error
which may be stored in 'errno' under some situations is 'EILSEQ'.
There are various places where an implementation defined value is set
in 'errno' but this does not really provide solid grounds for a
platform independent error reporting strategy.

Actually, it does. You can use strerror to get a string describing the
error, and then you can display that string to the user. So whether the
file does not exist or the permissions aren't right or whatever else, you
don't need to care in your program. You can just abort the operation that
was to be done and tell the user why it failed so he can fix it and try
again. In C++ streams, there is nothing like that. You can only tell the
user something like "Couldn't open file", which IMHO is not an appropriate
error message in a modern program.
 
D

Dietmar Kuehl

Rolf said:
Actually, it does. You can use strerror to get a string describing the
error, and then you can display that string to the user.

Indeed... I haven't thought of this. Of course:
In C++ streams, there is nothing like that. You can only tell the
user something like "Couldn't open file", which IMHO is not an appropriate
error message in a modern program.

.... you may have noticed that I'm maintaining the opinion that the
current standard already mandates setting of 'errno' in IOStreams.
Since there is currently no better alternative we should either

- clarify the standard to make it crystal clear that 'errno' is set
in the appropriate places in IOStreams.
- provide a "better" approach than 'errno'.

Is somebody filing a defect report on this issue? I would champion
the position that some details on the reasons of failures are
necessary in a portable way, although not necessarily by 'errno'
if there is a better alternative...
 
R

Rennie deGraaf

Dietmar said:
... you may have noticed that I'm maintaining the opinion that the
current standard already mandates setting of 'errno' in IOStreams.

I guess that, for now, I'll have to check if the compilers/libraries I
want to support (GCC, Sun CC, and MSVC++ 7 on Linux, OS X, Solaris, and
Win32, at least) set errno appropropriately and go with that.
Since there is currently no better alternative we should either

- clarify the standard to make it crystal clear that 'errno' is set
in the appropriate places in IOStreams.
- provide a "better" approach than 'errno'.

Is somebody filing a defect report on this issue? I would champion
the position that some details on the reasons of failures are
necessary in a portable way, although not necessarily by 'errno'
if there is a better alternative...

The "better alternative" would probably be to use exceptions. I'm not
particularly fond of Java's way of throwing a different type for every
possible error condition; I'd do something more like throw an
IOException, and include a enum type identifying the type of error; such
an enum would roughly correspond to all the values of errno that could
be set due to I/O operations.

However, I've never been fond of constructors throwing exceptions, as
catching them properly can do some nasty things to the structure of a
function/method in some cases. For instance, in Java (which uses
exceptions everywhere), if I wanted to open a bunch of sockets and be
able to tell which open failed, I could end up with something like this:
try {
Socket s1 = new Socket(host1, port1);
try {
Socket s2 = new Socket(host2, port2);
try {
Socket s3 = new Socket(host3, port3);
// do some socket I/O, and catch the associated exceptions
...
} catch (IOException e) {...}
} catch (IOException e) {...}
}catch (IOException e) {...}

Instead, I would prefer some mechanism such as returning an invalid
object on the failure of a constructor, having some mechanism to check
if a constructor succeeded, and throwing an exception if the invalid
object was accessed. Then, the above code would look more like this:
Socket s1 = new Socket(host1, port1);
Socket s2 = new Socket(host2, port2);
Socket s3 = new Socket(host3, port3);
if (s1.invalid()) {...}
if (s2.invalid()) {...}
if (s3.invalid()) {...}
// do some socket I/O, and catch the associated exceptions
....

Of course, this probably breaks OO badly enough to start some nice holy
wars among the purists. Does anyone have any better ideas?

Rennie
 

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

Members online

Forum statistics

Threads
474,201
Messages
2,571,049
Members
47,655
Latest member
eizareri

Latest Threads

Top