472,965 Members | 2,256 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,965 software developers and data experts.

How to fix compiler warning

I have a macro that I use across the board for freeing ram. I'd like to
clean up my code so I don't get these warnings.

#define sfree(x) _internal_sfree((void **)&x)
#define _internal_sfree(x) ({ if(x && *x) { free(*x); *x=NULL; } })

void main() {
char *x = (char *) malloc(10);
int *y = (int *) malloc(10);

sfree(x);
sfree(y);
}

results in:

warning: dereferencing type-punned pointer will break strict-aliasing
rules

Aug 24 '07 #1
28 2225
Dave Stafford wrote:
I have a macro that I use across the board for freeing ram. I'd like to
clean up my code so I don't get these warnings.

#define sfree(x) _internal_sfree((void **)&x)
#define _internal_sfree(x) ({ if(x && *x) { free(*x); *x=NULL; } })
Remove the extraneous parenthesis around the expression.
void main() {
If you didn't get a warning for this, crank up the warning level!

--
Ian Collins.
Aug 24 '07 #2
Ian Collins wrote:
Dave Stafford wrote:
>I have a macro that I use across the board for freeing ram. I'd like to
clean up my code so I don't get these warnings.

#define sfree(x) _internal_sfree((void **)&x)
#define _internal_sfree(x) ({ if(x && *x) { free(*x); *x=NULL; } })
Remove the extraneous parenthesis around the expression.
Which still leaves the question why cast to void** and why test for NULL?

How about:

#define sfree(x) _internal_sfree(&x)
#define _internal_sfree(x) { free(*x); *x=NULL; }

--
Ian Collins.
Aug 24 '07 #3
Dave Stafford <in*****@in.validwrites:
I have a macro that I use across the board for freeing ram. I'd like to
clean up my code so I don't get these warnings.

#define sfree(x) _internal_sfree((void **)&x)
#define _internal_sfree(x) ({ if(x && *x) { free(*x); *x=NULL; } })

void main() {
char *x = (char *) malloc(10);
int *y = (int *) malloc(10);

sfree(x);
sfree(y);
}

results in:

warning: dereferencing type-punned pointer will break strict-aliasing
rules
Your macro depends on a gcc-specific extension (see "Statement Exprs"
in the gcc manual).

You take care to avoid passing a null pointer to free(), but
free(NULL) is guaranteed to do nothing.

Take a look at the following version of your program.
================================
#include <stdlib.h>

#define SFREE(p) (free(p), (p) = NULL)

int main(void) {
char *x = malloc(10);
int *y = malloc(10 * sizeof *y);

SFREE(x);
SFREE(y);
return 0;
}
================================

Every change I made fixes a bug in your code:

main() returns int, not void. And since it returns int, you should
return an int.

I renamed the macro from "sfree" to "SFREE"; by convention, most
macros should have all-caps names.

In a macro definition, references to arguments should be enclosed in
parentheses to avoid operator precedence problems.

Casting the result of malloc() is useless, and can hide bugs.

You didn't have a '#include <stdlib.h>'. This is required if you're
going to call malloc(). The casts probably silenced your compiler's
warning about this, but didn't fix the bug (it's like snipping the
wire to a warning light on your car's dashboard).

Allocating 10 bytes for an int* doesn't make much sense if, for
example, sizeof(int) == 4. I changed it to allocate 10 ints.

Recommended reading: the comp.lang.c FAQ, <http://www.c-faq.com/>.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Aug 24 '07 #4
Ian Collins wrote:
Ian Collins wrote:
>Dave Stafford wrote:
>>I have a macro that I use across the board for freeing ram. I'd like to
clean up my code so I don't get these warnings.

#define sfree(x) _internal_sfree((void **)&x)
#define _internal_sfree(x) ({ if(x && *x) { free(*x); *x=NULL; } })
Remove the extraneous parenthesis around the expression.
Which still leaves the question why cast to void** and why test for NULL?

How about:

#define sfree(x) _internal_sfree(&x)
#define _internal_sfree(x) { free(*x); *x=NULL; }
Surely you should check that x!=NULL before calling *any* function on *x?

--
Philip Potter pgp <atdoc.ic.ac.uk
Aug 24 '07 #5
Philip Potter wrote:
Ian Collins wrote:
>Ian Collins wrote:
>>Dave Stafford wrote:
I have a macro that I use across the board for freeing ram. I'd
like to
clean up my code so I don't get these warnings.

#define sfree(x) _internal_sfree((void **)&x)
#define _internal_sfree(x) ({ if(x && *x) { free(*x); *x=NULL; } })

Remove the extraneous parenthesis around the expression.
Which still leaves the question why cast to void** and why test for NULL?

How about:

#define sfree(x) _internal_sfree(&x)
#define _internal_sfree(x) { free(*x); *x=NULL; }

Surely you should check that x!=NULL before calling *any* function on *x?
Good point! The noise got in the way...

--
Ian Collins.
Aug 24 '07 #6
Dave Stafford wrote:
I have a macro that I use across the board for freeing ram. I'd like to
clean up my code so I don't get these warnings.
What about those diagnostics you _should_ have gotten, but either didn't
get or forgot to tell us about?

You seem to have already taken the first step toward getting rid of the
diagnostics: you have set your diagnostic level too low. Lower it again
and maybe it will compile Fortran as C without complaint.
>
#define sfree(x) _internal_sfree((void **)&x)
#define _internal_sfree(x) ({ if(x && *x) { free(*x); *x=NULL; } })

void main() {
char *x = (char *) malloc(10);
int *y = (int *) malloc(10);

sfree(x);
sfree(y);
}

results in:

warning: dereferencing type-punned pointer will break strict-aliasing
rules
Aug 24 '07 #7
Philip Potter <pg*@see.sig.invalidwrites:
Ian Collins wrote:
>Ian Collins wrote:
>>Dave Stafford wrote:
I have a macro that I use across the board for freeing ram. I'd like to
clean up my code so I don't get these warnings.

#define sfree(x) _internal_sfree((void **)&x)
#define _internal_sfree(x) ({ if(x && *x) { free(*x); *x=NULL; } })

Remove the extraneous parenthesis around the expression.
Which still leaves the question why cast to void** and why test for NULL?

How about:

#define sfree(x) _internal_sfree(&x)
#define _internal_sfree(x) { free(*x); *x=NULL; }

Surely you should check that x!=NULL before calling *any* function
on *x?
That is not really a problem -- the x in _internal_sfree is always of
the form &... [Obviously this is only true if it is not invoked
directly, but there is no practical way to avoid problems if internal
helper macros are invoked by user code.]

Since the x is of the form &... and * and & "cancel each other out"
(talking very loosely) you end up not needing the other macro. With
the required extra parentheses, a comma expression rather than a
block, and a better name you get Keith's version:

#define SFREE(p) (free(p), (p) = NULL)

--
Ben.
Aug 24 '07 #8
Ben Bacarisse wrote:
Philip Potter <pg*@see.sig.invalidwrites:
>Ian Collins wrote:
>>Which still leaves the question why cast to void** and why test for NULL?

How about:

#define sfree(x) _internal_sfree(&x)
#define _internal_sfree(x) { free(*x); *x=NULL; }
Surely you should check that x!=NULL before calling *any* function
on *x?

That is not really a problem -- the x in _internal_sfree is always of
the form &... [Obviously this is only true if it is not invoked
directly, but there is no practical way to avoid problems if internal
helper macros are invoked by user code.]
Yes of course, I should have seen that before!

--
Philip Potter pgp <atdoc.ic.ac.uk
Aug 25 '07 #9
Philip Potter wrote:
Ben Bacarisse wrote:
>Philip Potter <pg*@see.sig.invalidwrites:
>>Ian Collins wrote:
Which still leaves the question why cast to void** and why test for
NULL?

How about:

#define sfree(x) _internal_sfree(&x)
#define _internal_sfree(x) { free(*x); *x=NULL; }
Surely you should check that x!=NULL before calling *any* function
on *x?

That is not really a problem -- the x in _internal_sfree is always of
the form &... [Obviously this is only true if it is not invoked
directly, but there is no practical way to avoid problems if internal
helper macros are invoked by user code.]

Yes of course, I should have seen that before!
See what happens when "function like" macros have lower case names :)

--
Ian Collins.
Aug 25 '07 #10
Ian Collins wrote:
Philip Potter wrote:
>Ben Bacarisse wrote:
>>Philip Potter <pg*@see.sig.invalidwrites:

Ian Collins wrote:
Which still leaves the question why cast to void** and why test for
NULL?
>
How about:
>
#define sfree(x) _internal_sfree(&x)
#define _internal_sfree(x) { free(*x); *x=NULL; }
Surely you should check that x!=NULL before calling *any* function
on *x?
That is not really a problem -- the x in _internal_sfree is always of
the form &... [Obviously this is only true if it is not invoked
directly, but there is no practical way to avoid problems if internal
helper macros are invoked by user code.]
Yes of course, I should have seen that before!
See what happens when "function like" macros have lower case names :)
How would it be any different if they were real functions?

--
Philip Potter pgp <atdoc.ic.ac.uk
Aug 25 '07 #11
Philip Potter <pg*@see.sig.invalidwrites:
Ian Collins wrote:
>Philip Potter wrote:
>>Ben Bacarisse wrote:
Philip Potter <pg*@see.sig.invalidwrites:

Ian Collins wrote:
>Which still leaves the question why cast to void** and why test for
>NULL?
>>
>How about:
>>
>#define sfree(x) _internal_sfree(&x)
>#define _internal_sfree(x) { free(*x); *x=NULL; }
Surely you should check that x!=NULL before calling *any* function
on *x?
That is not really a problem -- the x in _internal_sfree is always of
the form &... [Obviously this is only true if it is not invoked
directly, but there is no practical way to avoid problems if internal
helper macros are invoked by user code.]
Yes of course, I should have seen that before!
See what happens when "function like" macros have lower case names :)
How would it be any different if they were real functions?
The sfree() macro takes the address of its argument. If a function
did that, it would get the address of the parameter, a local object,
not the address of the object you pass to it.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Aug 25 '07 #12
Ian Collins said:
Dave Stafford wrote:
>void main() {

If you didn't get a warning for this, crank up the warning level!
Whilst it's wrong (except on some freestanding implementations), it
isn't a syntax error or a constraint violation. Implementations need
not diagnose it (although some choose to do so).

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Aug 25 '07 #13
Richard Heathfield wrote:
>
Ian Collins said:
Dave Stafford wrote:
void main() {
If you didn't get a warning for this, crank up the warning level!

Whilst it's wrong (except on some freestanding implementations), it
isn't a syntax error or a constraint violation. Implementations need
not diagnose it (although some choose to do so).
I don't see void main() as being as more or less correct
on freestanding implementations which define void main(),
than it is on hosted implementations which define void main().

--
pete
Aug 25 '07 #14
pete wrote:
Richard Heathfield wrote:
>Ian Collins said:
>>Dave Stafford wrote:

void main() {
If you didn't get a warning for this, crank up the warning level!
Whilst it's wrong (except on some freestanding implementations), it
isn't a syntax error or a constraint violation. Implementations need
not diagnose it (although some choose to do so).

I don't see void main() as being as more or less correct
on freestanding implementations which define void main(),
than it is on hosted implementations which define void main().
Section 5.1.2.2.1 of the standard does.

--
Ian Collins.
Aug 25 '07 #15
[comp.lang.c] Richard Heathfield <rj*@see.sig.invalidwrote:
Ian Collins said:
>If you didn't get a warning for this, crank up the warning level!
Whilst it's wrong (except on some freestanding implementations), it
isn't a syntax error or a constraint violation. Implementations need
not diagnose it (although some choose to do so).
I would think that an implementation worth its salt would provide a
warning level at which it did issue a diagnostic for void main(). Are
there any major implementations which cannot be coerced into doing so?

--
C. Benson Manica | I appreciate all corrections, polite or otherwise.
cbmanica(at)gmail.com |
----------------------| I do not currently read any posts posted through
sdf.lonestar.org | Google groups, due to rampant unchecked spam.
Aug 25 '07 #16
Christopher Benson-Manica said:
[comp.lang.c] Richard Heathfield <rj*@see.sig.invalidwrote:
>Ian Collins said:
>>If you didn't get a warning for this, crank up the warning level!
>Whilst it's wrong (except on some freestanding implementations), it
isn't a syntax error or a constraint violation. Implementations need
not diagnose it (although some choose to do so).

I would think that an implementation worth its salt would provide a
warning level at which it did issue a diagnostic for void main(). Are
there any major implementations which cannot be coerced into doing so?
Borland can, and gcc can. Last time I checked, which was VS6, Microsoft
couldn't.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Aug 25 '07 #17
Fr************@googlemail.com said:
On Aug 25, 12:45 pm, Richard Heathfield <r...@see.sig.invalidwrote:
>[...] C90 implementations must provide int main(int, char
**) and correct C90 programs must use int main(int char **) - not to
do so renders the behaviour of the program undefined.

I believe you are mistaken - in both C90 and C99, main can also take
no parameters. (It must still return an int of course.)
Whoops! Yes, of course it can instead take no parameters. Would you
believe me if I told you I knew that really? :-)

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Aug 25 '07 #18
Ian Collins <ia******@hotmail.comwrites:
pete wrote:
[...]
>I don't see void main() as being as more or less correct
on freestanding implementations which define void main(),
than it is on hosted implementations which define void main().
Section 5.1.2.2.1 of the standard does.
It says that main shall be defined as 'int main(void)', or as
'int main(int argc, char *argv[])', "or in some other
implementation-defined manner".

So 'void main(void)' is "correct" on an implementation (either hosted
for freestanding) that supports it.

By contrast, 'int main(void)' is correct on any hosted implementation
(and may or may not be correct on a given freestanding
implementation).

I was going to say which one of you I agree with, but the disagreement
is over words, not over what those words refer to, so I won't bother.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Aug 25 '07 #19
Christopher Benson-Manica wrote:
>
I would think that an implementation worth its salt would provide a
warning level at which it did issue a diagnostic for void main(). Are
there any major implementations which cannot be coerced into doing so?
I added a warning for
void main(void)
{
}

since lcc-win32 got into an obscure bug...

C99 mandates that main should return zero even if the programmer
doesn't explicitly write a return statement.

If you declare main as a void function however,
the compiler would try to make a void function return zero
as result!!!

A user warned me about this: the compiler crashed when it
saw

void main(void)
{}

I fixed it by ignoring the void statement. And added a
warning with a higher warning level.
Aug 25 '07 #20
jacob navia wrote, On 25/08/07 21:16:
Christopher Benson-Manica wrote:
>>
I would think that an implementation worth its salt would provide a
warning level at which it did issue a diagnostic for void main(). Are
there any major implementations which cannot be coerced into doing so?

I added a warning for
void main(void)
{
}
Good :-)
since lcc-win32 got into an obscure bug...

C99 mandates that main should return zero even if the programmer
doesn't explicitly write a return statement.

If you declare main as a void function however,
the compiler would try to make a void function return zero
as result!!!

A user warned me about this: the compiler crashed when it
saw

void main(void)
{}
You could have claimed it was not a bug because it did not affect
conformance to the C standard. You are explicitly allowed to fail to
compile a program that unconditionally invokes undefined behaviour, and
crashing counts.
I fixed it by ignoring the void statement. And added a
warning with a higher warning level.
Shucks. Still, even an obsolete compiler that crashes on void main() is
another reason not to use it :-)
--
Flash Gordon
Aug 28 '07 #21
On Sat, 25 Aug 2007 00:38:27 +0200 (CEST), Dave Stafford
<in*****@in.validwrote:
>I have a macro that I use across the board for freeing ram. I'd like to
clean up my code so I don't get these warnings.

#define sfree(x) _internal_sfree((void **)&x)
>#define _internal_sfree(x) ({ if(x && *x) { free(*x); *x=NULL; } })
There is no guarantee that casting &y to void** and then dereferencing
it will produce the void* containing the original value of y that you
want. Consider the case below where y is a int* and let sizeof
(void*) be 8 while all other pointers are 4.

There is even no guarantee that the value &x is properly aligned for a
void** value.
>
void main() {
char *x = (char *) malloc(10);
int *y = (int *) malloc(10);

sfree(x);
sfree(y);
}

results in:

warning: dereferencing type-punned pointer will break strict-aliasing
rules

Remove del for email
Aug 29 '07 #22
In article <fa**********@chessie.cirr.com>, Christopher Benson-Manica
<at***@otaku.freeshell.orgwrites
>[comp.lang.c] Richard Heathfield <rj*@see.sig.invalidwrote:
>Ian Collins said:
>>If you didn't get a warning for this, crank up the warning level!
>Whilst it's wrong (except on some freestanding implementations), it
isn't a syntax error or a constraint violation. Implementations need
not diagnose it (although some choose to do so).

I would think that an implementation worth its salt would provide a
warning level at which it did issue a diagnostic for void main(). Are
there any major implementations which cannot be coerced into doing so?
Yes, quite a few.

Most embedded cross compilers do not and should not.
In fact it is more useful if they give a warning to
int main()
as there is nothing to return to.

However I agree that in the hosted world a warning should be given.

These days I suspect the majority of C use is in the embedded world.
--
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
\/\/\/\/\ Chris Hills Staffs England /\/\/\/\/
/\/\/ ch***@phaedsys.org www.phaedsys.org \/\/\
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/

Aug 29 '07 #23
Barry Schwarz wrote:
On Sat, 25 Aug 2007 00:38:27 +0200 (CEST), Dave Stafford
<in*****@in.validwrote:
>I have a macro that I use across the board for freeing ram. I'd like to
clean up my code so I don't get these warnings.

#define sfree(x) _internal_sfree((void **)&x)
>#define _internal_sfree(x) ({ if(x && *x) { free(*x); *x=NULL; } })

There is no guarantee that casting &y to void** and then dereferencing
it will produce the void* containing the original value of y that you
want. Consider the case below where y is a int* and let sizeof
(void*) be 8 while all other pointers are 4.
Such an implementation would not be conforming AFAIK. sizeof(void *) ==
sizeof(char *).
There is even no guarantee that the value &x is properly aligned for a
void** value.
Values do not have alignment. This is why the following code works even though
shorts may have alignments that longs may not:

#include <stdio.h>
int main(void) {
short value = 10;
long lval = (long) value;
printf("%d\n",lval); /* Or should it be %ld? */
return 0;
}

Phil

--
Philip Potter pgp <atdoc.ic.ac.uk
Aug 29 '07 #24
Chris Hills wrote:
In article <fa**********@chessie.cirr.com>, Christopher Benson-Manica
<at***@otaku.freeshell.orgwrites
>[comp.lang.c] Richard Heathfield <rj*@see.sig.invalidwrote:
>>Ian Collins said:
>>>If you didn't get a warning for this, crank up the warning level!
>>Whilst it's wrong (except on some freestanding implementations), it
isn't a syntax error or a constraint violation. Implementations need
not diagnose it (although some choose to do so).

I would think that an implementation worth its salt would provide a
warning level at which it did issue a diagnostic for void main(). Are
there any major implementations which cannot be coerced into doing so?

Yes, quite a few.

Most embedded cross compilers do not and should not.
In fact it is more useful if they give a warning to
int main()
as there is nothing to return to.

However I agree that in the hosted world a warning should be given.

These days I suspect the majority of C use is in the embedded world.
That depends on how you define "the majority", I guess. I accept that your
statement may be correct for usage of C to get work done. But for learners of C,
I think the majority would be using hosted implementations on ordinary PCs.

Besides, I'm working on an embedded platform at the moment and the
implementation is hosted, not freestanding. (You just have to be careful not to
use any of the standard library calls (of which printf() is one) which may swell
your binary beyond 64Kb...)

Phil

--
Philip Potter pgp <atdoc.ic.ac.uk
Aug 29 '07 #25
On Wed, 29 Aug 2007 09:49:06 +0100, Philip Potter
<pg*@see.sig.invalidwrote:
>Barry Schwarz wrote:
>On Sat, 25 Aug 2007 00:38:27 +0200 (CEST), Dave Stafford
<in*****@in.validwrote:
>>I have a macro that I use across the board for freeing ram. I'd like to
clean up my code so I don't get these warnings.

#define sfree(x) _internal_sfree((void **)&x)
>>#define _internal_sfree(x) ({ if(x && *x) { free(*x); *x=NULL; } })

There is no guarantee that casting &y to void** and then dereferencing
it will produce the void* containing the original value of y that you
want. Consider the case below where y is a int* and let sizeof
(void*) be 8 while all other pointers are 4.

Such an implementation would not be conforming AFAIK. sizeof(void *) ==
sizeof(char *).
True. Let sizeof(void*) and sizeof(char*) be 8 while others are 4 and
the point remains valid.
>
>There is even no guarantee that the value &x is properly aligned for a
void** value.

Values do not have alignment. This is why the following code works even though
shorts may have alignments that longs may not:
Values assigned to pointers must satisfy alignment issues. &x is an
expression with type pointer to something. From 6.3.2.3-7:

"A pointer to an object or incomplete type may be converted to a
pointer to a different object or incomplete type. If the resulting
pointer is not correctly aligned for the pointed-to type, the behavior
is undefined."
>
#include <stdio.h>
int main(void) {
short value = 10;
long lval = (long) value;
All you have done here is cast an integer value to another integer
value of greater rank. This has nothing to do with alignment.

If you had said
long lval = *(long*)&value;
you would be addressing the issue at hand and in fact invoking
undefined behavior on all systems where sizeof(long)>sizeof(short).
The UB is the result not only of possible alignment issues but also of
accessing bytes beyond the end of value.
printf("%d\n",lval); /* Or should it be %ld? */
Yes.
return 0;
}

Remove del for email
Aug 31 '07 #26
In article <+U**************@phaedsys.demon.co.uk>
Chris Hills <ch***@phaedsys.demon.co.ukwrote:
>Most embedded cross compilers do not [warn about "void main"]
That may well be the case, although I cannot speak for "most" or even
"many".
>and should not.
Here, I disagree: "should" or "should not" is too strong, and I think
I disagree even more strongly with this:
>In fact it is more useful if they give a warning to
int main()
as there is nothing to return to.
Often enough, there *is* something to return to: the assembly code
that calls the startup routine. This may well just reboot, if that
suffices for an error recovery method.

Since I, in embedded environments, tend to name my "C startup
routine" start() (not main()), it does not affect me one way or
another what any given compiler thinks of the symbol "main". I
recommend this practice to all embedded-systems writers: do not
use main() at all, unless it will have return type "int" and the
two Standard C arguments.
>However I agree that in the hosted world a warning should be given.

These days I suspect the majority of C use is in the embedded world.
Perhaps. Of course, on vxWorks 6.x, RTPs are entered at main()
with the two Standard C arguments (plus, admittedly, several more
that one can use or ignore as desired -- specifically "char **envp",
a la Unix-like systems, and "void *aux", which is ... difficult to
describe) and the return value from main() is made available to
the task that collects the RTP's exit status.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Sep 2 '07 #27
In article <fb********@news1.newsguy.com>, Chris Torek
<no****@torek.netwrites
>In article <+U**************@phaedsys.demon.co.uk>
Chris Hills <ch***@phaedsys.demon.co.ukwrote:
>>Most embedded cross compilers do not [warn about "void main"]

That may well be the case, although I cannot speak for "most" or even
"many".
>>and should not.
Here, I disagree: "should" or "should not" is too strong, and I think
I disagree even more strongly with this:
Then we shall have to disagree.

>>In fact it is more useful if they give a warning to
int main()
as there is nothing to return to.
Often enough, there *is* something to return to: the assembly code
that calls the startup routine. This may well just reboot, if that
suffices for an error recovery method.
All the asm start up code I have seen is a linear piece of code whose
final instruction is something like "jmp _main" There is no return
point.

More to the point return statement in main will have nothing to return
to. It will be completely undefined (unless there is an OS)

Despite what the embedded OS vendors will have you believe the use of an
OR or RTOS in embedded systems is still quite uncommon.

So where is this "return" supposed to go? Having a return that does
something indeterminate is dangerous in many embedded systems.
Therefore there should be no return.

If it gets that far wrong you need a re-boot or of course an infinite
lop and let the watchdog take over.

Doing a return from many is just dangerous as the program exits into the
ether....
>Since I, in embedded environments, tend to name my "C startup
routine" start() (not main()), it does not affect me one way or
another what any given compiler thinks of the symbol "main". I
recommend this practice to all embedded-systems writers: do not
use main() at all, unless it will have return type "int" and the
two Standard C arguments.
Fair enough. However many (most?) of the embedded debug tools look for
"main" as a start point so often you get no choice.

--
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
\/\/\/\/\ Chris Hills Staffs England /\/\/\/\/
/\/\/ ch***@phaedsys.org www.phaedsys.org \/\/\
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/

Sep 2 '07 #28
Chris Hills wrote:
>
.... snip ...
>
All the asm start up code I have seen is a linear piece of code
whose final instruction is something like "jmp _main" There is
no return point.
Sounds as if you have been stuck with poor systems. Everything I
have built, or designed, called main (or the appropriate
equivalent), and either rebooted or halted if there was no
controlling shell to return to. Before any halt they would emit an
alerting message if the hardware permitted.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

--
Posted via a free Usenet account from http://www.teranews.com

Sep 2 '07 #29

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
by: Sony Antony | last post by:
I have the following simple program in Solaris Forte compiler 5.4 producing the warning. Though it produces the warning, it works fine as expected. This has been compiling fine without any...
7
by: Matthew Del Buono | last post by:
Don't try to solve the problem. I've found a way -- around or fixing it. I'm just curious as to whether this is Microsoft's problem in their compiler or if there's a standard saying this is to be...
1
by: Hafeez | last post by:
I am having real trouble compiling this code http://www.cs.wisc.edu/~vganti/birchcode/codeHier/AttrProj.tgz The attachment shows errors when compiled using the current version of g++ in a...
29
by: junky_fellow | last post by:
Consider the following piece of code: struct junk { int i_val; int i_val1; char c_val; }; int main(void) {
34
by: Bob | last post by:
Hi, The compiler gives Warning 96 Variable 'cmdSource' is used before it has been assigned a value. A null reference exception could result at runtime. Dim cmdSource as SQlClient.SQLDataReader...
8
by: Charles Sullivan | last post by:
I have a program written in C under Linux (gcc) which a user has ported to run under AT&T SysV R4. He sent me a copy of his makelog which displays a large number of compiler warnings similar to...
11
by: Charles Sullivan | last post by:
I have a number of functions, e.g.: int funct1( int arg1, int arg2, int arg3 ); int funct2( int arg1, int arg2, int arg3 ); int funct3( int arg1, int arg2, int arg3 ); that are called via...
11
by: zeppe | last post by:
Hi all, I've a problem. The code that follows creates a warning in both gcc and visual c++. However, I think it's correct: basically, there is a function that return an object of a derived...
10
by: Ivan Vecerina | last post by:
Here's a relatively simple code snippet: #include <memory> class Base { public: Base(); virtual ~Base(); virtual void f(int a, char const* name);
3
by: gil | last post by:
Hi, I'm trying to find the best way to work with compiler warnings. I'd like to remove *all* warnings from the code, and playing around with the warning level, I've noticed that compiling with...
0
by: Aliciasmith | last post by:
In an age dominated by smartphones, having a mobile app for your business is no longer an option; it's a necessity. Whether you're a startup or an established enterprise, finding the right mobile app...
4
NeoPa
by: NeoPa | last post by:
Hello everyone. I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report). I know it can be done by selecting :...
3
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be using a very simple database which has Form (clsForm) & Report (clsReport) classes that simply handle making the calling Form invisible until the Form, or all...
1
by: Teri B | last post by:
Hi, I have created a sub-form Roles. In my course form the user selects the roles assigned to the course. 0ne-to-many. One course many roles. Then I created a report based on the Course form and...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM) Please note that the UK and Europe revert to winter time on...
3
by: nia12 | last post by:
Hi there, I am very new to Access so apologies if any of this is obvious/not clear. I am creating a data collection tool for health care employees to complete. It consists of a number of...
0
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be focusing on the Report (clsReport) class. This simply handles making the calling Form invisible until all of the Reports opened by it have been closed, when it...
0
isladogs
by: isladogs | last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, Mike...
2
by: GKJR | last post by:
Does anyone have a recommendation to build a standalone application to replace an Access database? I have my bookkeeping software I developed in Access that I would like to make available to other...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.