T.R | Title | User | Personal Name | Date | Lines |
---|
2102.1 | 64 bit porting problem | MUCTEC::BECKER | Hartmut B., VMS & Languages, Munich | Fri Feb 21 1997 04:44 | 10 |
| In your example you left out the fmt1 argument in the fprintf call. But
that's not the problem. Your (or his) example works in a 32 bit
environment, it doesn't in a 64 bit environment. The call to err passes
strings where err expect ints. Adresses are 64 bit long, ints are 32 bit
long, they don't match. As a temporary solution you might want to use
-taso. It works as expected for your example but you might want to make
your code 64 bit clean.
Hope this helps,
Hartmut
|
2102.2 | Better workaround | WIBBIN::NOYCE | Pulling weeds, pickin' stones | Fri Feb 21 1997 10:15 | 9 |
| Does that mean it would help to add this line to err?
void * A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U;
(or char * should work as well, in case some compilers don't like it.)
Nevertheless, this is not a valid C program, since you call a function
with a different number of arguments than what it is declared to take,
and you don't use the varargs mechanism.
|
2102.3 | Try stdarg and vsprintf | DECCXL::WIBECAN | That's the way it is, in Engineering! | Fri Feb 21 1997 10:17 | 46 |
| >> In your example you left out the fmt1 argument in the fprintf call. But
>> that's not the problem.
Well, it is the problem in that it causes the seg fault on the first call to
err(). But it isn't the only problem, as you point out.
>> Your (or his) example works in a 32 bit
>> environment, it doesn't in a 64 bit environment. The call to err passes
>> strings where err expect ints. Adresses are 64 bit long, ints are 32 bit
>> long, they don't match. As a temporary solution you might want to use
>> -taso. It works as expected for your example but you might want to make
>> your code 64 bit clean.
To give a little more detail, the unspecified arguments to err are defaulting
to int. You are actually passing char pointers, and sprintf and fprintf are
expecting char pointers. The conversion to int is dropping the high 32 bits.
You might want to re-code this using a full prototype for err() with "..."
format, use stdarg to handle the argument list, and use vsprintf instead of
sprintf for the first sprintf call. Something like this:
#include <stdarg.h>
[other #include directives and code for main() omitted]
void err (char *file, int line, char *fmt, ...)
{
FILE *ft;
char fmt1[1024],fmt2[1024],efile[100],date[20],time[20];
va_list ap;
sprintf(fmt1, "%s%s", "", fmt);
/*
** Merged strcpy, strcat, and part of first sprintf call
** into a single sprintf. I wasn't sure what the purpose
** of the sprintf of "" into fmt2 was. You could consider
** dropping it if it is always a null string.
*/
va_start (ap, fmt); /* Set up variable arg access */
vsprintf(fmt2, fmt1, ap); /* Like sprintf but with var args */
va_end (ap); /* Done with variable arg access */
sprintf(fmt1,"%s[%d]:%s", file, line, fmt2);
fprintf(stderr, "%s\n",fmt1);
return;
}
|
2102.4 | Wrong is wrong... | DECC::SULLIVAN | Jeff Sullivan | Fri Feb 21 1997 12:16 | 18 |
| As the previous replies stated, the code in the base note is and was always
incorrect. It just so happened to work on other (inferior) operating systems.
Brian's suggestion in .3 is a good one. That is, you should always use stdargs
for variable argument functions.
There are a couple of pages that describe stdargs (recommended for ANSI C) and
varargs (supported for K&R) at the Cygnus website.
See
http://www.cygnus.com/pubs/gnupro/5_libraries/b_libc/libchtmlANSIstandard_macros
_stdargh.html
and
http://www.cygnus.com/pubs/gnupro/5_libraries/b_libc/libchtmlTraditional_macros_
varargsh.html
-Jeff
|
2102.5 | unfortunately: wrong is valid | MUCTEC::BECKER | Hartmut B., VMS & Languages, Munich | Fri Feb 21 1997 15:41 | 8 |
| The program is valid and it's not wrong in terms of ANSI C. It simply exploits
the lack of a proper data model in C. And the data model changes if you go from
the inferior operating system to the superior one.
That it is poor programming style and that it is a poor algorithm for variable
arguments is the other side of the coin.
Hartmut
|
2102.6 | The program is only valid if you consider undefined behavior valid. | CXXC::REPETE | Rich Peterson 381-1802 ZKO2-3/N30 | Fri Feb 21 1997 17:28 | 26 |
| RE .5:
> The program is valid and it's not wrong in terms of ANSI C.
It might arguably be considered sort of valid under K&R C in
the sense that K&R first edition is completely silent on the
subject of what happens when you have a function call with
a different number of arguments than the number of formal
parameters in its definition, and that this style was more
or less common practice before the invention of varargs.h.
But it is quite clearly designated as having undefined behavior
under ANSI C 3.3.2.2 (ISO 6.3.2.2) "Functions calls":
"If the expression that denotes the called function has a type that
does not include a prototype, the integral promotions... If the
number of arguments does not agree with the number of parameters,
the behavior is undefined."
RE .2:
> void * A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U;
This meant to say:
void *A,*B,*C,*D,*E,*F,*G,*H,*I,*J,*K,*L,*M,*N,*O,*P,*Q,*R,*S,*T,*U;
|