main() in C90

A

Al Balmer

Richard Bos said:
Billy Bong said:
On Wed, 16 Jan 2008 22:15:29 +0200, Ioannis Vranos wrote:

Hi, in C90 is "int main()" valid, the same as "int main(void)" and "int
main(int argc, char *argv[])"?

AFAIK in C99 only "int main(void)" and "int main(int argc, char
*argv[])
- and the **argv syntax" are the only valid ones.

You've forgotten a variation. In C89, main() is also valid, as an
old-style declaration. I'm not sure about main(void) and main(int argc,
char **argv), since they seem to be a mix of old-style and prototype,
but since they're perverse anyway I'm not going to look it up. Any of
those are, in any case, not allowed under C99.
In reality, "void main()" is also valid.

No, it isn't. It may be widely accepted, but then, so is jaywalking.

I found it odd that "void main()" gets 5 times as many hits on Google as
"int main(void)".

Is that the new standard of correctness?Did you notice that the majority of the hits, at least in the first
three pages, say that the usage is incorrect?
 
H

Harald van Dijk

In reality, "void main()" is also valid.

Some compilers issue a warning for this, but you can safely ignore this
warning in 99.999999% or six sigma of the time.

You're more likely to be struck by lightning than come across a compiler
that does not both accept and work with no problems with "void main()".

void main() will be rejected by gcc when compiling with the options
-pedantic-errors -Wall
which I normally do for my own code. I haven't been struck by lightning
yet.
 
B

Bart C

Richard Tobin said:
Googling for "void main()" is identical to googling for "void main".

Two thirds of them are in fact "static void main", so they are probably
not C code at all.

Maybe not. But the rest would still outnumber "int main(void)" :)

If it is in fact that common an error, and is tolerated by compilers, then
why not just allow it? It would mean 'I'm declaring a main() function that
takes no parameters and doesn't explicitly return any value'. The compiler
can stick a return value in there if it likes.
I found zillions of references to Al Gore saying he invented the
Internet. Perhaps we should get him to say it, so they'd be true.

100 years from now it might well be true..
 
J

jacob navia

Harald said:

That document says

As always, the range of undefined behavior permitted includes:

* Corrupting memory

....

GREAT!

And it stays that way because those people refuse to improve C.
It took ages of discussions in comp.std.c to declare gets() deprecated.

No improvements to the library, no improvements to error handling
NOTHING, unless you are called Microsoft Corp of course.
 
J

jacob navia

Yeah, one sentence, without adornment, 7.26.9, that reads:
"The gets function is obsolescent, and is deprecated."

How bold.

It's a standard, not a user guide. The people who need warning about
gets() are not likely to be looking in the standard for guidance.

And of course the Rationale explains what's wrong with it.

-- Richard[/QUOTE]

The why did they leave it in the standard?
Why they refuse to fix asctime()'s buffer overflow?
 
R

Randy Howard

That document says

As always, the range of undefined behavior permitted includes:

* Corrupting memory

...

GREAT!

And it stays that way because those people refuse to improve C.


How would you limit the range of what can happen when the behavior is
"undefined"? If you did, then it would be undefined anymore. I can
see that you are upset, but that isn't the bet you should be upset
about, imo.
 
W

Walter Roberson

That document says
As always, the range of undefined behavior permitted includes:
* Corrupting memory

And it stays that way because those people refuse to improve C.

The only way to avoid the possibility of corrupting memory would
be to require that each object had attached attributes describing
the datatypes and permitted indices; and for any member of a union,
the type last used to store into that location or an indicator
that that location is not currently the starting location for
the object that was last stored into that area of memory. And
the types and indices and union compatabilities would have to be
checked for every access (that the compiler could not prove was
consistant with the previous check), and there would have to be
standardized mechanisms to detect and handle any problems
encountered. In environments with multiple threads or processes
with shared memory, avoiding the possibility of corrupting memory
might also require built-in mandatory semaphores or other such locking
schemes that would have to be keyed over memory address spans
(so as to avoid corruption if the threads or processes disagree
about where the start of the object is.)

These things could be done, but would the result still be C?
 
H

Harald van Dijk

How would you limit the range of what can happen when the behavior is
"undefined"? If you did, then it would be undefined anymore.

Why should it be undefined? Even if you don't want to fully define one
particular behaviour, which I can understand, would there be any
difficulty for any implementation if the behaviour were implementation-
defined instead?

And if any implementation has a real problem with not corrupting memory
while calling asctime with a valid struct tm, or if the possibility of
any such implementation is considered realistic, it would have been
possible to make this restriction on asctime explicit.
"If timeptr->tm_year is not between -2899 and 8099 (inclusive), the
behavior is undefined."
It wouldn't have caused any implementation to no longer conform, it would
be a great clarification to the standard, and it would be a hint to
implementors to mention this in the user documentation for asctime (which
in some cases is even derived from the text of the C standard).
 
C

Charlton Wilbur

BC> If it is in fact that common an error, and is tolerated by
BC> compilers, then why not just allow it? It would mean 'I'm
BC> declaring a main() function that takes no parameters and
BC> doesn't explicitly return any value'. The compiler can stick a
BC> return value in there if it likes.

It is allowed, if the compiler documents it as an additional allowed
prototype for main(). There's just no requirement that the compiler
do so.

Charlton
 
J

jacob navia

Randy said:
How would you limit the range of what can happen when the behavior is
"undefined"?

The behavior for out of range arguments is NOT SPECIFIED.
They didn't take the trouble of SAYING that years should
be smaller than 10000, and months/days should be smaller than 31.

They presented code that crashes at the slightest bad input and
they wrote that code into the standard document.
If you did, then it would be undefined anymore. I can
see that you are upset, but that isn't the bet you should be upset
about, imo.


Why not fixing it? Why did they REJECT the fix proposed to them?

I proposed it again one year ago.

Nothing.
 
J

jacob navia

Walter said:
The only way to avoid the possibility of corrupting memory would
be to require that each object had attached attributes describing
the datatypes and permitted indices;

Yes. Years must be unsigned smaller than 10000
Month and days must be smaller than 99.

NOT VERY DIFFICULT!
and for any member of a union,
the type last used to store into that location or an indicator
that that location is not currently the starting location for
the object that was last stored into that area of memory. And
the types and indices and union compatabilities would have to be
checked for every access (that the compiler could not prove was
consistant with the previous check), and there would have to be
standardized mechanisms to detect and handle any problems
encountered. In environments with multiple threads or processes
with shared memory, avoiding the possibility of corrupting memory
might also require built-in mandatory semaphores or other such locking
schemes that would have to be keyed over memory address spans
(so as to avoid corruption if the threads or processes disagree
about where the start of the object is.)

These things could be done, but would the result still be C?

This is irrelevant. You mean that if the committee specified
the above limits foe asctime() C would "change its nature"

???
 
R

Richard Heathfield

[asctime]

jacob navia said:
The behavior for out of range arguments is NOT SPECIFIED.
They didn't take the trouble of SAYING that years should
be smaller than 10000, and months/days should be smaller than 31.

The limits are easily deduced from 4.12.3.1 of C90 or 7.23.3.1 of C99. For
the buffer not to overflow:

tm_wday must be in the range 0-6.
tm_mon must be in the range 0-11.
tm_mday must be in the range 0-999(!).
tm_hour must be in the range 0-99.
tm_min must be in the range 0-99.
tm_sec must be in the range 0-99.
tm_year must be in the range 0-8099.

I don't see what's so hard. Nor will any of these limits be exceeded (for
the next few millennia, at any rate) if you pass in the address of a
struct tm that has been properly normalised by mktime. Incidentally, the
mktime spec directs you "above", to 4.12.1 (C89) or 7.23.1(4) (C99), where
more stringent limits are clearly laid out:

int tm_sec; // seconds after the minute - [0, 60]
int tm_min; // minutes after the hour - [0, 59]
int tm_hour; // hours since midnight - [0, 23]
int tm_mday; // day of the month - [1, 31]
int tm_mon; // months since January - [0, 11]
int tm_year; // years since 1900
int tm_wday; // days since Sunday - [0, 6]
int tm_yday; // days since January 1 - [0, 365]
int tm_isdst; // Daylight Saving Time flag
They presented code that crashes at the slightest bad input and
they wrote that code into the standard document.

strcpy can do the same. So can free. And fclose. And atoi. So what? When
calling standard library functions (or indeed any functions), it is the
programmer's responsibility to provide appropriate input data. C is not a
straitjacket. It's a power tool. Don't Cut Yourself.
Why not fixing it?

Because it's not broken.
 
H

Harald van Dijk

[asctime]
jacob navia said:
The behavior for out of range arguments is NOT SPECIFIED. They didn't
take the trouble of SAYING that years should be smaller than 10000, and
months/days should be smaller than 31.

The limits are easily deduced from 4.12.3.1 of C90 or 7.23.3.1 of C99.
For the buffer not to overflow:

tm_wday must be in the range 0-6.

This is specified in 7.23.1, as you noted.
tm_mon must be in the range 0-11.

This is specified in 7.23.1, as you noted.
tm_mday must be in the range 0-999(!).

This is specified in 7.23.1, with the range 1-31, as you noted.
tm_hour must be in the range 0-99.

This is specified in 7.23.1, with the range 0-23, as you noted.
tm_min must be in the range 0-99.

This is specified in 7.23.1, with the range 0-59, as you noted.
tm_sec must be in the range 0-99.

This is specified in 7.23.1, with the range 0-60, as you noted.
tm_year must be in the range 0-8099.

This is *not* specified in 7.23.1. Additionally, I see no reason to
assume the valid values start at 0.
I don't see what's so hard. Nor will any of these limits be exceeded
(for the next few millennia, at any rate) if you pass in the address of
a struct tm that has been properly normalised by mktime.

How can mktime normalise a tm_year >8099 to <8099? Programs can get that
as valid input. It doesn't require waiting until that year finally passes
by. In a related real-world example, a corrupted last modification
timestamp (retrieved using system-specific functions, printed using
standard C) on a file was able to cause several tools to segfault because
they made the same assumption you're making here.
strcpy can do the same.

This is obvious.
So can free.

This is obvious.
And fclose.

This is obvious.
And atoi.

This is non-obvious but explicit.

With asctime(), the problem is non-obvious and merely quietly suggested.
 
J

jameskuyper

Walter said:
The only way to avoid the possibility of corrupting memory would
be to require that each object had attached attributes describing
[long, compilcated overly general solution]

What's wrong with simply changing the behavior of asctime() by
replacing "sprintf(result," with "snprintf(result, sizeof(result)," in
7.23.3.1p2? That would seem to be sufficient to prevent the buffer
overrun. There are other, more complicated ways of preventing it which
will, under some circumstances, produce more useful results, but this
is at least sufficient.
 
J

jacob navia

Walter said:
The only way to avoid the possibility of corrupting memory would
be to require that each object had attached attributes describing
[long, compilcated overly general solution]

What's wrong with simply changing the behavior of asctime() by
replacing "sprintf(result," with "snprintf(result, sizeof(result)," in
7.23.3.1p2? That would seem to be sufficient to prevent the buffer
overrun. There are other, more complicated ways of preventing it which
will, under some circumstances, produce more useful results, but this
is at least sufficient.

There are MANY solutions. The one proposed and that the committee
rejected was to replace overflowing numbers with the asterisk (*)
character. That would give visual feedback, stay within the
sacred (but arbitrary) 26 chars buffer size. WHY they do not fix that
is a mystery.
 
C

CBFalconer

jacob said:
You can't read?


And where it says that should be smaller than 8099 ???

NOWHERE.

You failed to read Richards post, and especially you snipped the
following from it:

I think part of the confusion may be that the C90 reference should
actually be C89. The illiteracy suggestion is not appropriate.
 

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

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,078
Latest member
MakersCBDBlood

Latest Threads

Top