| February 1, 2007 - 5:44am Guest  | The following 'printf()' causes an application crash: int tty_printf(const char GENERIC *format, ...){
 int ret;
 va_list ap;
    va_start(ap, format);ret = sprintf(PrintBuf.buf, format, va_arg(ap, const char GENERIC *) );
 Comms_WrStr(PrintBuf.buf);
 va_end(ap);
 
 return ret;
 }
 Here's the listing. 'Comms_WrStr() was commented out to shorten it. Something doesn't look right.             ; FUNCTION _tty_printf (BEGIN); SOURCE LINE # 12
 0000 900000  R      MOV    DPTR,#format
 0003 EB             MOV    A,R3
 0004 F0             MOVX   @DPTR,A
 0005 A3             INC    DPTR
 0006 EA             MOV    A,R2
 0007 F0             MOVX   @DPTR,A
 0008 A3             INC    DPTR
 0009 E9             MOV    A,R1
 000A F0             MOVX   @DPTR,A
 ; R7 is assigned to ap
 ; SOURCE LINE # 17
 000B E581           MOV    A,__SP__
 000D C3             CLR    C
 000E 9402           SUBB   A,#02H       <------ backup to before the PC - OK
 ; SOURCE LINE # 18
 0010 24FD           ADD    A,#0FDH      <------ Subtract a genric ptr (3) - OK
 0012 04             INC    A                     <------ Add 1!! What's this!!
 0013 F8             MOV    R0,A               <------ Copy 3 bytes from the arg list
 0014 E6             MOV    A,@R0                       to the top of stack
 0015 C0E0           PUSH   ACC
 0017 08             INC    R0
 0018 E6             MOV    A,@R0
 0019 C0E0           PUSH   ACC
 001B 08             INC    R0
 001C E6             MOV    A,@R0
 001D C0E0           PUSH   ACC
 001F 7B02           MOV    R3,#002H
 0021 7A00    R      MOV    R2,#HIGH PrintBuf+002H
 0023 7900    R      MOV    R1,#LOW PrintBuf+002H
 0025 900000  R      MOV    DPTR,#format
 0028 120000  R      LCALL  ?C_X2TRI0
 002B 120000  R      LCALL  ?sprintf
 002E 74FD           MOV    A,#0FDH
 0030 2581           ADD    A,SP
 0032 F581           MOV    SP,A
 0034 900000  R      MOV    DPTR,#ret
 0037 EE             MOV    A,R6
 0038 F0             MOVX   @DPTR,A
 0039 A3             INC    DPTR
 003A EF             MOV    A,R7
 003B F0             MOVX   @DPTR,A
 ; SOURCE LINE # 22
 003C 900000  R      MOV    DPTR,#ret
 003F E0             MOVX   A,@DPTR
 0040 FE             MOV    R6,A
 0041 A3             INC    DPTR
 0042 E0             MOVX   A,@DPTR
 0043 FF             MOV    R7,A
 ; SOURCE LINE # 23
 0044 22             RET
             ; FUNCTION _tty_printf (END) The copy of the variable arg pointer looks offset by one byte. That's from       #define va_arg(ap,t) (*(t __Stack_Space__ *)((ap-=sizeof(t))+1)) in 'main_c51.h'. However removing the '+1' from the macro doesn't doesn't fix the crash' so something else isn't right.  As a crosscheck, the lines inside tty_printf() work fine when placed inline in the application. Compiler settings are:large memory model
 xdata pointers
 internal stack
      thanks Steven Pruzina | 
          
Oops.. The above code can never work. A function with a variable arg list can't pass that list to another function; it doesn't know how long the list is and so can't fix-up the stack.
However I did notice that function with a variable arg list has to be declared 'reentrant' for the compiler to pass parameters (to it) on the stack. The keyword is there to make a function reentrant by forcing parameters AND local variables onto the stack; a function which has a variable arg list but does NOT have to be reentrant shouldn't need this keyword (which will needlessly stack it's local variables)
Steven Pruzina
Hi,
I am having similar problems.
I believe that your posted code is valid in ANSI C,we have all used similar logger indirections (on many different development environments) since our earliest coding days!
I found that if I call a function or two below main() that it will work & even work if I return from those functions all the way back to main and then down again. Weird.
Would be interested in how you got on.
Hi Dudes,
This is an easy one: You are confusing between the variable arguments list and the pointer to this list.
You must use the vsprintf function for what you intend to do.
Here is you corrected example, I tested it and it works fine:
#include
#include
char PrintBuf[32];
int tty_printf(const char *format, ...)
{
int ret;
va_list ap;
va_start(ap, format);
ret = vsprintf(PrintBuf, format, ap); /* vsprintf, *not* sprintf! */
puts(PrintBuf);
va_end(ap);
return ret;
}
void main(void)
{
tty_printf( "%d %s", 3, "Hello" );
while(1);
}
I hope this helps,
Bruno
Thanks Bruno.
I missed the obvious mistake with the original post.
My code is similar to your corrected code and my code fails, rather fails if I call from main, 'works' when called lower down.
xdata char strBuffer[200];
void bio_printf( const char *a_Fmt, ... )
{
xdata va_list args;
xdata int Size, i;
va_start( args, a_Fmt );
vsprintf( strBuffer, a_Fmt, args );
va_end( args );
// printf( "Buffer size %d\n", strlen(strBuffer) );
/* if( (Size=strlen( strBuffer )) > 100 )
{
strBuffer[99-1] = '\0';
printf( "Output buffer overflow(%d) - %s", Size, strBuffer );
}
*/
printf( "%s", strBuffer );
return ;
} //-- endfn bio_printf() --//
(The printf() just substitutes my low level I/O. I originally started investigating why I could not print floats and ended up debugging the debug code.....)
When calling bio_printf() from main() I have identified that:
bio_printf( "text" )
But no further arguments causes program to crash.
bio_printf( "text %d, i )
Called from main displays some value other than i but otherwise does not crash.
bio_printf("text %d", i)
Called from some function below main displays i
bio_printf("text %f", f)
Displays text and no value.
My original problem was that I cannot print floats but I have eneded up with debugging some stack frame problem!
For me, Bruno's function does not work on floats either. Specifically, a bcd double under FP(BCD,ALL) using %7.4lf format. I am evaluating RIDE over Keil specifically because I need BCD variables which Keil does not have, but I am having very little luck so far. Not only does the above vsprint not work, but also sprintf exhibits the same problems if the bcd double is local rather than global. Heck, even 1.00 + 1.00 = 0.00 if the variables are local. The only thing I found in the FAQ that looked relevant was to use OMF51 setting but it made no difference. LARGE mode, external stack.
PeterH