Horrible Visual C Bug!

A

Arthur J. O'Dwyer

Kevin said:
The 'void main' is usually just the tip of the iceberg. It does
serve well as a "clueless-newbie" alert.
Things like using differing parameters... [snip]
You see several of these, and you are almost guaranteed
to have a "void main".

Your first point is a logical implication in the forward direction.
But your substantiation at the end is in the reverse direction.
Logical errors like these also serve well as a "clueless" alert...

Not at all. Note Kevin's use of "almost guaranteed," implying a
probabilistic approach. Let us assume that 75% of C programmers
are clueless newbies; 99% of clueless newbies make some fundamental
error; 50% of experts make some fundamental error; 33% of clueless newbies
use void main; and 0% of experts use void main. Then Kevin's assertions
are "almost all" valid. ;)

Given 'void main', what is the probability of further errors
in the same program? 99%.

Given that we see 'void main', what is the probability that we
are dealing with a clueless newbie? 100%.
Things like using differing parameters... [snip]
You see several of these, and you are almost guaranteed
to have a "void main".

Given one or more fundamental errors in the same program, what
is the probability that we have a 'void main'? 57.3%. Not
guaranteed, but more than even.

Suppose only 10% of expert C programmers make fundamental errors
in their programs. Then the probability of 'void main' given
a fundamental error rises to 64.8%.

Not "almost guaranteed", I guess, but that *was* given the possibly
conservative assumption that only 33% of newbies write 'void main'.
Maybe it's a higher fraction.

-Arthur
 
C

Carsten Hansen

Mark McIntyre said:
On Wed, 23 Jul 2003 18:07:45 -0400, in comp.lang.c ..
..
..
And secondly, if void main() /is/ defined, the compiler writer is
obliged to document it. MS products do NOT document it, in fact the
reverse, they state that main must return an int. The fact that their
sample code doesn't do that is merely bad quality control.
..
..
Mark McIntyre

I'm not in favor of void main. However, I don't think your statement is
correct.
Here is one page of Microsoft's documentation:

Carsten Hansen

---------------
A special function called main is the starting point of execution for all C
and C++ programs.
If you are writing code that adheres to the Unicode programming model, you
can use the
wide-character version of main, wmain.

The main function is not predefined by the compiler; rather, it must be
supplied in the
program text.

The declaration syntax for main is:

int main( );
or, optionally:

int main( int argc[ , char *argv[ ] [, char *envp[ ] ] ] );
Microsoft Specific

The declaration syntax for wmain is as follows:

int wmain( );
or, optionally:

int wmain( int argc[ , wchar_t *argv[ ] [, wchar_t *envp[ ] ] ] );
END Microsoft Specific

The types for argc and argv are defined by the language. The names argc,
argv, and envp
are traditional, but are not required by the compiler. See Argument
Definitions for more
information and for an example.

Alternatively, the main and wmain functions can be declared as returning
void (no return
value). If you declare main or wmain as returning void, you cannot return an
exit code
to the parent process or operating system using a return statement; to
return an exit
code when main or wmain is declared as void, you must use the exit function.

See Also
C++ Keywords | Using wmain Instead of main | main Function Restrictions
 
F

Falcon Kirtarania

You are perfectly welcome to turn the warning level down to none, if you
want to. Of course, in one of microsoft's libraries in which _int32 and
_int64 are declared (basetd.h), it sets the warning level for one of the
warnings to level 4, but it shouldn't cause a problem.
 
F

Falcon Kirtarania

Syntax and Specification of main() including void main() as per Microsoft
Visual C++:
Program Startup: the main Function
A special function called main is the entry point to all C++ programs. This
function is not predefined by the compiler; rather, it must be supplied in
the program text. If you are writing code that adheres to the Unicode
programming model, you can use the wide-character version of main, wmain.
The declaration syntax for main is:

int main( );

or, optionally:

int main( int argc[ , char *argv[ ] [, char *envp[ ] ] ] );

The declaration syntax for wmain is as follows:

int wmain( );

or, optionally:

int wmain( int argc[ , wchar_t *argv[ ] [, wchar_t *envp[ ] ] ] );

Alternatively, the main and wmain functions can be declared as returning
void (no return value). If you declare main or wmain as returning void, you
cannot return an exit code to the parent process or operating system using a
return statement; to return an exit code when main or wmain are declared as
void, you must use the exit function.

Therefore, it is painfully clear that the only specified effect in
Microsoft's compiler is that a void main() cannot return anything except via
exit. Not that this is valid ANSI C, of course, but it clearly specifies
what Microsoft's compiler is supposed to do.
 
F

Falcon Kirtarania

Which would explain exactly why Microsoft programs are so poor: their
compiler accepts a program return type that is theoretically seen as
nonsense to the OS and therefore the program should raise many errors when
run. However, their own programmers are not aware of that standard or their
sample code would involve no void main(). However, it must be legal in
Windows because the compiler somehow manages to compile it on that platform.
I wonder, if it was compiling for unix, would it be allowed to compile void
main()?

Herbert Rosenau said:
This is a multiple choice message.

.... a stupid programmer?

S/h/i/t thinks that void() main is the real truth because on his
computer is nothing than his own crap and main() gets invoked
magically only, so nothing happens that s/h/i/t has not in s/h/i/ts
own hands.

... an intelligent programmer who looks outside his onw work?

He/she knows that there is at least one instance on his computer that
invokes applications like an application invokes functions. So he
knows of exactly 2 different ways(*) to write his entry point from the
OS:

1. int main(void)

This interface is fine defined by the standard and the OS. What does
it mean?

a) the application returns an int to its caller to tell it about its
success or fail.
b) the application doen't use a single argument, it will still ignore
any whenever the caller will give one or more.

But in any way it will inform itzs caller correctly about its success
or if it fails why.

2. int main(int argc, char *argv[])

This interface differs only in the way that the application is aware
of arguments the caller may have choosen. It will look at them, it
will check them and works with.

But as the developer knows about the backgrounds he/she prepares the
whole application in the defined manner as the application will always
tell about its success.

... an application

An application behaves like a function inside an application. It gets
called from somewhere and the caller awaits a result. The caller likes
to get 0 or EXEI_SUCCESS every tome the application had worked well
and something unequal to that to be a hint that something went wrong.
So whenever the application returns a random number because the stupid
programmer was really crazy something random can occure.

Each application has an entry point that gets invoked when after
loading it gets called the first time. This entry point is well hidden
from the C application developer, because there is many different work
to do to serve the developer with a functional environment. An
incomplete list:

- initialise all static and extern variables not already done in the
binary file
- preparing the standard streams stdin, stdout and stderr to be clean
to use
- cleaning up internal resources (like memory management, file
handler,
direct API ointerfaces, and much more)
- setting up the backdoors (like exit(), signal handlers...)
- call the initial fuction by
- getting the parameters given by the caller
- prparing them to be matching the given rules (argc, argv)
- starting the first developer defined subroutine, known as main
- collecting the result from main
- close all resources the developer may have left open
- write outstanding buffers into theyr streams
- close open files, including stdin, stderr, stdout
- freeing memory the developer has left alone
- convey the result from main to the OS to let it convey it to the
caller
- flag the OS: I've done anything, remove me from the task list,
giving up all rights to use the CPU.

... an OS?

The OS offers one or more APIs to allow an application to invoke other
applications. It defines in that interface(s) a method to get the
result from that application. This is exactly the value given on
return in main or the value given as parameter to exit() and a flag
that tells that the OS was failing to execute the application.
Whenever main() of the called application returns others than the well
defined return values (0, EXIT_SUCCESS, EXIT_FAILTURE or an
implementation defined one it may occure that the OS will tell the
caller that it was unable to success the called application - even as
it has done all well - except to return an int from main.

Conclusion:

Any time a crazy programmer fails to return an int in main s/h/e/it
opens the doors wide for in best case unspezified behavior. Same as if
he writes an function, spezifiing that it returns a pointer and let
this function return without a given value.

The only reason no prototype for main exist is that main can be
defined in different ways, without receiving parameters and with
receiving parameters - but it must return always int because interface
description in each OS requires this.
This requirement is at least much older than K$R C and its precursors.

I have enough trust in the poeple who program these compilers that if they
went out of their way to provide void main(void) compilation, they insured
it would not trash anything.

This defines you as crazy programmer who doesn't care that there are
environments aroud who crashes when main() dosen't return int, who
lets the caller of an application die when main comes back with a
random number.

Go on, try to write a framework that does nothing than to call other
applications and does different work when an application tells it was
successfully completed and the application comes back with an error.
Be sure, you will ever fail if crazy M$ has written that application,
because it fails always in the standard. But means that you can ignore
any standard (even in M$ OSes?). No, it means only you proves you only
as ignorant, who is not interested in quality, security and stability.


(*) In practice the implementation may or may not define one or more
different ways to define interfaces to main - but at least all defines
that main returns int, some of them may offer a third or forth
parameter, but as this is only implementation defined that doesn't
matter here, because we're speaking only about the standard here.






--
Tschau/Bye

Herbert Rosenau
http://www.pc-rosenau.de eComStation Reseller in Germany
eCS 1.1 GA englisch wird jetzt ausgeliefert
 
F

Falcon Kirtarania

Probably what explains it better is that if there is no order in which
something may be done, the compiler may order it however it wants. In this
case, it is doing it in efficient orders based on different assumptions
(running on a pentium, running on a pentium pro, ignoring certain checks,
etc.). The compiler in that case is perfectly valid. And the aforesaid
statement is actually quite correct.
 
F

Falcon Kirtarania

C is C, regardless of the compiler and also regardless of the program,
provided both conform to standards. Therefore, depending on application,
MSVC6 may be a better choice than GCC. However, Microsoft's programs are
very poorly written and therefore waste system resources as if they were
saltwater in the Dead Sea. However, that does not mean that MSVC6 will
compile our programs to act in that way, or it would not be compiling C.
 
T

Terence Hoosen

Is there any standard specifying that any programmer that has a void main
will also have the aforementioned errors in all their programming? No?
Then your logic is slightly flawed. However, it is not bad logic because it
alerts that somebody has not been taught proper C.

I think that's almost exactly what I said :)

-Tez
 
J

Joona I Palaste

Terence Hoosen <[email protected]> scribbled the following
I think that's almost exactly what I said :)

Let me just say, if a programmer writes void main() because he/she does
not know better, that's all right. If a programmer knows fully well that
the only accepted form of main() is int main(), and writes void main()
anyway, _out of sheer spite_, that really gets my goat. There have been
hints towards that in this very thread.

--
/-- Joona Palaste ([email protected]) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/
"A computer program does what you tell it to do, not what you want it to do."
- Anon
 
R

Ron Natalie

Christian Bau said:
(These two possibilities alone would be enough to make you avoid a
statement like this, obviously. But don't mention that your program
could crash or worse because of this).

Well, saying it is undefined behavior should be sufficient. You can't
make any predictions other than that.
 
C

Christian Bau

"Arthur J. O'Dwyer said:
Given that we see 'void main', what is the probability that we
are dealing with a clueless newbie? 100%.

It could also be someone who has been writing C code for many years, and
is still clueless.
 
C

Christian Bau

"Falcon Kirtarania said:
Which would explain exactly why Microsoft programs are so poor: their
compiler accepts a program return type that is theoretically seen as
nonsense to the OS and therefore the program should raise many errors when
run. However, their own programmers are not aware of that standard or their
sample code would involve no void main(). However, it must be legal in
Windows because the compiler somehow manages to compile it on that platform.
I wonder, if it was compiling for unix, would it be allowed to compile void
main()?

Good question. Having a main () function declared as "void main ()"
invokes undefined behavior. That means that according to the C Standard,
anything could happen. And when I say anything, I mean _absolutely
anything_. If you compile and run this program:

void main () { printf ("Hello, world\n"); }

then it could happen that your computer explodes, or your harddisk gets
formatted, and you can't complain that your compiler is not a Standard C
compiler. (You still can complain that a common mistake like that
shouldn't explode your computer, but you can't complain that the
compiler is not conforming to the C Standard. )

You can check the documentation for your compiler. Maybe it defines what
will happen; if the C Standard leaves something undefined then any
compiler is allowed to define it. Maybe your compiler refuses to compile
the program; I would say that would be a very sensible approach. Maybe
your program crashes as soon as you start it, maybe it crashes just when
it finishes. Maybe the operating system puts up an alert that says:
"Warning: Program xxxx seems to be broken. Please contact the
manufacturer of this program for further advice. ". Anything could
happen.
 
M

Mark McIntyre

This is, in fact, one of them.

Sure about that?
However, it's only required to issue some
diagnostic. A compiler that prints "There might be errors." every time
it runs is compliant.

Sure. As is one that prints "Compiling..."
 
M

Mark McIntyre

Is it really? Quite a few people have looked for Microsoft's C documentation
of the effect of void main. I don't think anyone has found it yet.

(and someone responded with a quote from the MSVC 6 helpfile,
mentioning void main() but I managed to lose the post)

I was about to say "interesting, so MS finally documented it" but then
I noticed that this section begins "A special function called main is
the entry point to all C++ programs".
 
L

Lucian Wischik

Arthur said:
Not at all. Note Kevin's use of "almost guaranteed," implying a
probabilistic approach. Let us assume that 75% ...

Right, although you could equally well make assumptions that push the
probabilities in the other direction.

e.g. a disease has a 0.1% occurence in the general population, and
there is a test for it with 99% accuracy. If you take the test and get
a positive result then, all other things being equal, it's
overwhelmingly likely that you DON'T have the disease.


("cluelessness" would be the 0.1% thing. but yeah, it's probably
closer to your estimate than to 0.1%.)
 
B

Bruce Wheeler

I'm quoting form the online documentation to Microsoft Visual Studio .NET
2003. So, apparently Microsoft has improved their documentation.

Carsten Hansen

Maybe someday Microsoft will get their documentation correct :-(

That section is in the VS.NET C++ Language Reference, so its relevance
to C programs is questionable.

However, it appears that they really intended the section to apply to
both C and C++, since the corresponding section in the C Language
Reference from VC6 has been removed for VS.NET.

Going back to what Mark McIntyre wrote
and secondly, if void main() /is/ defined, the compiler writer is
obliged to document it. MS products do NOT document it, in fact the
reverse, they state that main must return an int. The fact that their
sample code doesn't do that is merely bad quality control.

The change appears to be another case of bad quality control. If the
section is meant to apply to both languages, it should be in as section
common to both languages (the infamous C/C++), or the section should be
repeated in the C Language Reference.

Regards,
Bruce Wheeler
 
R

Richard Bos

Carsten Hansen said:
I'm quoting form the online documentation to Microsoft Visual Studio .NET
2003. So, apparently Microsoft has improved their documentation.

For values of "improved" that include to "worsened", IYAM.

Richard
 
R

Richard Bos

Lucian Wischik said:
Right, although you could equally well make assumptions that push the
probabilities in the other direction.

e.g. a disease has a 0.1% occurence in the general population, and
there is a test for it with 99% accuracy. If you take the test and get
a positive result then, all other things being equal, it's
overwhelmingly likely that you DON'T have the disease.

Erm, no. If it's 99% accurate, and it comes out positive, the odds are
99 to 1 that you _do_ have the disease. That's what 99% accuracy means.
Note that tests are rarely equally accurate for positive and negative
results, though.

Richard
 
R

Ron Natalie

Mark McIntyre said:
Sure about that?

Yep. The compiler must complain about the syntax and diagnosable
semantic errors unless the standard says no diagnostic is required.
The standard says main "SHALL" return int. This means the program
is not well-formed if it doesn't, and since there's no exemption clause,
it needs a diagnostic.
 
R

Ron Natalie

Christian Bau said:
Good question. Having a main () function declared as "void main ()"
invokes undefined behavior.

Actually, it's an error the compiler is supposed to catch as far as the standard
goes.
 

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,077
Messages
2,570,566
Members
47,202
Latest member
misc.

Latest Threads

Top