code

  • Thread starter Bill Cunningham
  • Start date
L

lawrence.jones

Nick Keighley said:
hmmm. The Standard does not guarantee that fopen() sets errno
(which is what the machinary of perror() uses underneath). But
many implementaions *do* set errno. This includes such obscure
platforms as Windows and most (all?) Unix platforms. This is one
place where I accept the technically non-portability and call
perror() after a failed fopen() (well actually I prefer strerror()).

Traditional stdio implementations set errno to a reasonable value
somewhat coincidentally in most failure cases, but not all of them. If
you hit one of the rare cases where it did not, you would get a leftover
value from some unrelated failure, either from within fopen itself or
from a previous call, which can be quite puzzling (the most common
leftover value is ENOTTY: Not a tty). So, you have to balance the
advantage of potentially getting helpful information against the
disadvantage of potentially getting misleading information. I generally
come to the same conclusion that you do -- the gain outweighs the rare
pain.
 
B

Bill Cunningham

Keith Thompson said:
Why are you wasting our time posting this crap?

You obviously haven't tried to compile it. I see at least one syntax
error, at least one constraint violation. (There are several other
serious errors as well, aside from the fact that you've posted a code
fragment rather than a complete program.)

Do not attempt to call a standard library function without first
reading and understanding its documentation, particularly its expected
arguments and return value. Do not post code here that you haven't at
least attempted to compile. Until that sinks in, nothing else I can
say will be of any help to you.

I did compile it and had no problems. I agree this is getting old I
think it might be time to let this thread die.

Bill
 
K

Keith Thompson

Bill Cunningham said:
I did compile it and had no problems. I agree this is getting old I
think it might be time to let this thread die.

You did not compile the code that you posted. If you had, your
compiler would have notified you of the syntax error. I suspect you
re-typed the code for posting rather than copy-and-pasting it. Never
do that.

Go back to your article from upthread, copy-and-paste the code you
posted into a file, and try compiling it. Here's the code, exactly as
you posted it:

FILE *fp;
if((fp=fopen("data","wb"))=='\0' {
perror("fopen");
clearerr("fopen");
exit(EXIT_FAILURE);
}

Oh, and *please* indent properly, even for a tiny fragment like this.

But ok, to answer your original question, the argument to perror can
be a function name, but it doesn't have to be. The string will be
included in the error message that's shown to the user. Usually it's
more useful to use a file name, but using a function name may be what
you want in some circumstances. It's not a matter of correctness (as
long as you pass a pointer to *some* string).
 
D

Default User

Keith said:
Sure, but its behavior depends on the value of errno, and his implicit
assumption that fopen() sets errno on an error is not entirely
portable.

But the worst thing that can happen is a confusing error message,
perhaps something like "Error opening file: No error", or "Error
opening file: Your fly is open" (the latter is admittedly unlikely).

The one implementation that I used which didn't set errno for this
situation (I think Greenhills for VxWorks, but I can't remember) said
something like: "error 0".




Brian
 
N

Nate Eldredge

Keith Thompson said:
Sure, but its behavior depends on the value of errno, and his implicit
assumption that fopen() sets errno on an error is not entirely
portable.

But the worst thing that can happen is a confusing error message,
perhaps something like "Error opening file: No error", or "Error
opening file: Your fly is open" (the latter is admittedly unlikely).

However, there does seem to be a tradition of implementations
including a few joke error codes in <errno.h>. glibc, notably,
includes EGRATUITOUS, EGREGIOUS, EIEIO, and ED ("The experienced user
will know what is wrong"). FreeBSD is a bit more sedate but does
include EDOOFUS. I have always wanted to find an excuse to use one of
these.
 
K

Kalle Olavi Niemitalo

Nate Eldredge said:
However, there does seem to be a tradition of implementations
including a few joke error codes in <errno.h>. glibc, notably,
includes EGRATUITOUS, EGREGIOUS, EIEIO, and ED ("The experienced user
will know what is wrong").

The Hurd support in glibc uses EGRATUITOUS, EGREGIOUS, and EIEIO.
 
J

Joachim Schmitz

Bill said:
If perror's use isn't portable as it sounds like your saying,
maybe it shouldn't be used. My system is partly posix since linux
doesn't completely conform but I do have solaris too. If it's not
totally portable I don't want to get into the habit of using it.
Atleast til I'm more experience in portability.


perror() is portable, relying on fopen() to set errno is not, hence relying
on perror() to give a reasonable error message in case fopen() failes is not
portable

User perror() (or strerror() or errno) only at failure of function calls
that are specified to set errno.

Bye, Jojo
 
J

Joachim Schmitz

Bill said:
I looks for 248 that it prints whatever you want it to. Like
another puts. Then mentions strerror in section B3. Is perror(fp)
right? Or perror("This is wrong"); I don't want to irritate you
Richard I value your wisdom but this irritates me.

perror() takes a char *, actually pointer to a C string (a '\0' terminated
sequence of chars), does fp qualify? Does "This is wrong" qualify?

Bye, Jojo
 
G

Giorgos Keramidas

I don't think so.

What Barry Schwarz wrote *is* true, though.

The following program builds without any diagnostic messages in either
'c89' or 'c99' mode with gcc 4.2.1:

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

3 int
4 main(void)
5 {
6 char *error = '\0';

7 (void)printf("error=%p\n", error);
8 return EXIT_SUCCESS;
9 }

One would probably expect line 6 to issue a diagnostic, but it doesn't.

If line 6 is replaced with

char *error = 1;

then a diagnostic *is* displayed by gcc in both std=c89 and std=c99 mode:

foo.c:7: warning: initialization makes pointer from integer without a cast

It is the special case of an integer that is zero that is, well,
`special'. There is no diagnostic message, and the pointer is
initialized to the system specific value of a null pointer.
 
G

Giorgos Keramidas

However, there does seem to be a tradition of implementations
including a few joke error codes in <errno.h>. glibc, notably,
includes EGRATUITOUS, EGREGIOUS, EIEIO, and ED ("The experienced user
will know what is wrong"). FreeBSD is a bit more sedate but does
include EDOOFUS. I have always wanted to find an excuse to use one of
these.

Heh!

Well, EDOOFUS isn't exactly a `joke value', because it is *used* in some
parts of the kernel. In my local version of the 8.0-CURRENT source tree
there are at least the following instances:

keramida@kobe:/usr/src/sys$ fgrep -nr EDOOFUS *
boot/efi/libefi/errno.c:89: errno = EDOOFUS;
dev/hwpmc/hwpmc_mod.c:2439: return EDOOFUS; /* programming error */
dev/md/md.c:1102: error = EDOOFUS;
dev/puc/puc.c:445: return (EDOOFUS);
dev/puc/puc_cfg.c:50: error = EDOOFUS;
geom/bde/g_bde_lock.c:414: return (EDOOFUS); /* Programming error */
geom/part/g_part.c:1332: error = EDOOFUS;
geom/part/g_part.c:1365: error = EDOOFUS; /* Prevent bogus uninit. warning. */
geom/part/g_part.c:1798: error = (arg == (uintptr_t)scheme) ? EDOOFUS : arg;
kern/subr_witness.c:1003: return (EDOOFUS);
sys/errno.h:168:#define EDOOFUS 88 /* Programming error */
keramida@kobe:/usr/src/sys$

Reading through a few cases where EDOOFUS appears, it looks more like a
catch-all value, meaning ``Oops! This wasn't meant to _ever_ happen.
Something looks remarkably screwed up, so let's break out of the kernel
and avoid making a more serious mess of anything.''.
 
F

Flash Gordon

Giorgos Keramidas wrote, On 04/10/08 04:27:
What Barry Schwarz wrote *is* true, though.

The following program builds without any diagnostic messages in either
'c89' or 'c99' mode with gcc 4.2.1:

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

3 int
4 main(void)
5 {
6 char *error = '\0';

7 (void)printf("error=%p\n", error);
8 return EXIT_SUCCESS;
9 }

One would probably expect line 6 to issue a diagnostic, but it doesn't.

'\0' is just another way of spelling 0. Strange but true.
If line 6 is replaced with

char *error = 1;

then a diagnostic *is* displayed by gcc in both std=c89 and std=c99 mode:

foo.c:7: warning: initialization makes pointer from integer without a cast

That warning is entirely correct. The C standard (all versions) require
a warning.
It is the special case of an integer that is zero that is, well,
`special'. There is no diagnostic message, and the pointer is
initialized to the system specific value of a null pointer.

The special case is specifically an integer *constant* expression that
evaluates to 0, so ((42-42)/42) would also work, and it is guaranteed to
set the pointer to a null pointer whatever than means in terms of bit
patterns. However, the following would not
const int zero = 0;
char *pre = zero;
 

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

code question 74
sh?tpile of errors 82
How can I view / open / render / display a pdf file with c code? 0
Command Line Arguments 0
How to fix this code? 1
seg fault 76
comparison error 12
code 34

Members online

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,217
Latest member
topweb3twitterchannels

Latest Threads

Top