Re: Partial string loss with sprintf/strcat



On Mon, 31 Jul 2006 05:11:18 +0000, Dave Thompson wrote:
Like other responders I don't see any likely culprits in the partial
code you posted. As already suggested collecting information about the
state and sequence(s) leading up to a fault is likely to be helpful in
narrowing down the suspects, and/or helping you construct cases that
will reproduce it in test. I realize general advice like this is not
much more helpful than telling you that candy tastes good.

Well, I suppose it is a small comfort to me that I'm not crazy and didn't
overlook something patently obvious. After further research I do believe
that I have a better idea of what is going on. The stack and heap size
must be pre-declared and it appears as if the declared stack size is too
small. The stack space is being exceeded (or so it appears). I have
given the stack an additional 1000 bytes and will do further testing to
see if this resolves the issue. If it doesn't I'm in trouble. :-) With
that change to the stack size that puts my memory usage at 16302 bytes out
of 16384. Talk about pushing the limits... :-O

It may be obvious, but if you haven't done so already I would inspect
the generated (and I assume shipped) assembler/machine code for your
routine and if reasonably possible (and not prohibited) for the library
routines your code calls (sprintf, strcat, etc.) just to make sure the
compiler/implementor isn't doing something dumb somewhere. (But that
part would be offtopic for c.l.c, except maybe for questions about
exactly what standard-library routines are required to do, especially in
corner cases, which I don't see you approaching.)

A good suggestion but it's been years since I inspected assembler level
code. And this machine uses a modified variant of the "Amsterdam
compiler" that compiles to EM byte-code. The machine runs an interpreter
that translates the EM code to native machine calls. I suppose there may
be enough information out there to learn more about the EM byte code and
figure things out, but that will probably be a last resort.

I do however see something I would do differently in a memory
constrained environment (and maybe even a normal one) which might or
might not be of help to you. Instead of building the message body in one
buffer (tmpMsg) and then copying it plus a small fixed-length prefix
into another (Message), do something like:
size_t used = sprintf (&Message[4], "format", headerargs); strcpy
(&Message[4+used], nextitem); used += nextitemlen; etc., bumping used
in the process as long as not too difficult char tmpLen [4+1]; sprintf
(tmpLen, "%04d", used /* or strlen (Message+4) */ ); memcpy
(&Message[0], tmpLen, 4);
/* you can simplify &Message[n] to Message+n and particularly
&Message[0] to Message if your compiler is so badly lame it doesn't */

I already rewrote the function to do exactly what you are suggesting
(though implemented a little differently). It should now be more
efficient as well as likely being easier to see which call is causing me
the issue. We'll see if this makes a difference.

If the code generated, by your compiler for your target*, to access
(within) the global/static buffer is less efficient, use a pointer into
it instead:
/* register? */ char * putMsg = &Message[4]; putMsg += sprintf
(putMsg, "format", headerargs); etc.
(* For 8080 and IIRC Z80, linker-resolved globals or statics are
actually better, but I don't know if Z180 is different here.)

Also, if you have snprintf (or _snprintf or somesuch) available in your
library, you might use that instead. (It is standard in C99 for hosted
environments, but I'd guess the implementation you're using isn't even
trying to conform at that level.) For the code and data you posted it
doesn't look likely that you're overflowing, but it could be arbitrarily
bad if you do, so if you can be certain at reasonable cost you don't
it's probably worth it just to rule that out.

I do not have a snprintf of any sort available to me. The compiler I'm
using is ANSI C89 conforming, but that's as far as it goes (The compiler
was written in 1993). I thought about using a third party library (such
as trio), but in the end I decided that it wasn't worth linking against
any additional code. Size is too important when the program gets
downloaded at 2400/1200baud.

I appreciate all of the replies I have received. I apologize for asking
the question and then more-or-less disappearing. I was out of town on
training and didn't have Usenet access. But all of the suggestions have
been much appreciated.

.



Relevant Pages

  • Re: Do buffers always start with the lowest memory address being the first element?
    ... > The C standard does not assume a downward-growing stack, ... > an upward-growing stack. ... C allows but does not require that the array produced ... > machine depends on both the C compiler and the machine. ...
    (comp.lang.c)
  • Re: switch statement, was compiler, status...
    ... Primary Register, Secondary Register, ... Stack, and abit of storage does it. ... This version of Small-C is copyrighted as a revision to Ron Cain's ... Croatia) is "Calculator Compiler" by Senko Rasik. ...
    (alt.lang.asm)
  • Re: back online again...
    ... really "acceptable") convention. ... stack machine, but the design ... target with my compiler (may need a different name for this though, ... most of this code is not likely to ever go to object files anyways... ...
    (alt.lang.asm)
  • Re: 2.6.25-git2: BUG: unable to handle kernel paging request at ffffffffffffffff
    ... since the compiler is totally free to spill and reload the local variable ... So forget about the prefetch, ... variable onto the stack, since it did that volatime memory access through ... the insane "store and immediately reload from ...
    (Linux-Kernel)
  • Re: Source code size and debug disabled
    ... different to the C++ compiler, could this be a feature introduced by the ... My suggestion would be to split the one huge file down into a number of more ... feature of producing a lib rather than a dll. ... >> After the limit source line information is not available. ...
    (microsoft.public.vc.debugger)