Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > My error or fprintf implementation error ?

Reply
Thread Tools

My error or fprintf implementation error ?

 
 
Jos De Laender
Guest
Posts: n/a
 
      08-14-2003
Following simple program :

#include <stdio.h>

char *Convert(int Arg) {
static char Buffer[128];
printf("Convert called for %d\n",Arg);
sprintf(Buffer,"%d",Arg);
printf("Convert about returning %s\n",Buffer);
return Buffer;
}

main() {
printf("%s %s\n",Convert(10),Convert(56));
}

Generates output :

[jos@krekel TestStaticString]$ ./a.out
Convert called for 56
Convert about returning 56
Convert called for 10
Convert about returning 10
10 10

This is puzzling me a lot as I would expect 10 56

Can someone enlighten me on my error ?
I'm using gcc 2.96 on a Mandrake Linux system.

Thanks.

Jos
 
Reply With Quote
 
 
 
 
Jens.Toerring@physik.fu-berlin.de
Guest
Posts: n/a
 
      08-14-2003
Jos De Laender <(E-Mail Removed)> wrote:
> Following simple program :


> #include <stdio.h>


> char *Convert(int Arg) {
> static char Buffer[128];
> printf("Convert called for %d\n",Arg);
> sprintf(Buffer,"%d",Arg);
> printf("Convert about returning %s\n",Buffer);
> return Buffer;
> }


> main() {
> printf("%s %s\n",Convert(10),Convert(56));
> }


> Generates output :


> [jos@krekel TestStaticString]$ ./a.out
> Convert called for 56
> Convert about returning 56
> Convert called for 10
> Convert about returning 10
> 10 10


> This is puzzling me a lot as I would expect 10 56


Sorry, but this is not an error of (f)printf(). When you call
it it receives three arguments. The first one is a pointer to
the format string, the second is the return value of a call of
Convert(10) and the third the return value of the call of
Convert(56). So both calls of Convert() are done *before*
printf() itself is invoked. But since both calls of Convert()
write into the same memory area, the static char array Buffer[],
the second call overwrites the result of the first call before
(f)printf() has a chance to print out the first result. You
can also see nicely that that the arguments to printf() aren't
necessarily evaluated left to right, any sequence the compiler
writers prefer is allowed and one should never rely on a certain
behavior.
Regards, Jens
--
_ _____ _____
| ||_ _||_ _| http://www.velocityreviews.com/forums/(E-Mail Removed)-berlin.de
_ | | | | | |
| |_| | | | | | http://www.physik.fu-berlin.de/~toerring
\___/ens|_|homs|_|oerring
 
Reply With Quote
 
 
 
 
Ben Pfaff
Guest
Posts: n/a
 
      08-14-2003
Jos De Laender <(E-Mail Removed)> writes:

> char *Convert(int Arg) {
> static char Buffer[128];
> printf("Convert called for %d\n",Arg);
> sprintf(Buffer,"%d",Arg);
> printf("Convert about returning %s\n",Buffer);
> return Buffer;
> }
>
> main() {
> printf("%s %s\n",Convert(10),Convert(56));
> }


There's only one static buffer. You can't use it twice and
expect it to magically have different two values at once.
--
"Large amounts of money tend to quench any scruples I might be having."
-- Stephan Wilms
 
Reply With Quote
 
jacob navia
Guest
Posts: n/a
 
      08-14-2003

> Thanks. Sounds reasonable.
>
> What would be a solution to avoid this ?
> I can think of
> X) Never calling it twice within printf , but that will go wrong one
> day ...
> X) Making a dynamic allocation instead of a static buffer. But then
> deallocation must be systematically done for avoiding leaks ...
> (cumbersome)
>
> Other suggestions ?
>


Yes. Add an argument to that function: The buffer where it should print
the stuff.
No allocations, no problems


 
Reply With Quote
 
Jos De Laender
Guest
Posts: n/a
 
      08-14-2003
Eric Sosman wrote:
>
> Jos De Laender wrote:
> > [...]
> > > > main() {
> > > > printf("%s %s\n",Convert(10),Convert(56));
> > > > }
> > > [where Convert() fills in and returns a pointer to a static buffer]

> >
> > What would be a solution to avoid this ?
> > I can think of
> > X) Never calling it twice within printf , but that will go wrong one
> > day ...
> > X) Making a dynamic allocation instead of a static buffer. But then
> > deallocation must be systematically done for avoiding leaks ...
> > (cumbersome)

>
> I once implemented a similar function that had a small
> array of static buffers and used them cyclically. That
> let me call the function multiple times within a single
> printf(), so long as I didn't call it more times than the
> function had buffers. (Yes, Your Honor, I know it was wrong.
> But I was in a hurry, and it was throw-away code, and I swear
> I'll never do it again, and I throw myself on the mercy of
> the Court. Aren't you up for re-electon soon?)


Hehe

Good suggestion after all.

My code will have thousands of those calls. So I'm really looking for a
solution where caller doesn't have to bother about buffers and cleanup.
And I know for sure - this is God told me in person - that there
will be no printf with more than 5 of those calls to Convert.

So thanks !

Jos

>
> In addition to the two approaches you mention (and the
> above hackish elaboration on the first of them, which I
> really don't recommend), there's the possibility of making
> the caller of Convert() responsible for managing the buffer.
> That is, instead of having Convert() provide the static or
> dynamic memory to hold the result, ask the caller to provide
> it and let Convert() simply fill it in. Then it's the
> caller's responsibility to provide different buffers for
> "contemporaneous" calls, to clean up dynamic allocations,
> and so on.
>
> --
> http://www.velocityreviews.com/forums/(E-Mail Removed)

 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      08-15-2003
Jos De Laender wrote:
> (E-Mail Removed)-berlin.de wrote:
> > Jos De Laender <(E-Mail Removed)> wrote:
> >
> > > Following simple program :

> >
> > > #include <stdio.h>

> >
> > > char *Convert(int Arg) {
> > > static char Buffer[128];
> > > printf("Convert called for %d\n",Arg);
> > > sprintf(Buffer,"%d",Arg);
> > > printf("Convert about returning %s\n",Buffer);
> > > return Buffer;
> > > }

> >
> > > main() {
> > > printf("%s %s\n",Convert(10),Convert(56));
> > > }

> >
> > > Generates output :

> >
> > > [jos@krekel TestStaticString]$ ./a.out
> > > Convert called for 56
> > > Convert about returning 56
> > > Convert called for 10
> > > Convert about returning 10
> > > 10 10

> >
> > > This is puzzling me a lot as I would expect 10 56

> >
> > Sorry, but this is not an error of (f)printf(). When you call
> > it it receives three arguments. The first one is a pointer to
> > the format string, the second is the return value of a call of
> > Convert(10) and the third the return value of the call of
> > Convert(56). So both calls of Convert() are done *before*
> > printf() itself is invoked. But since both calls of Convert()
> > write into the same memory area, the static char array Buffer[],
> > the second call overwrites the result of the first call before
> > (f)printf() has a chance to print out the first result. You
> > can also see nicely that that the arguments to printf() aren't
> > necessarily evaluated left to right, any sequence the compiler
> > writers prefer is allowed and one should never rely on a certain
> > behavior.

>
> Thanks. Sounds reasonable.
>
> What would be a solution to avoid this ?
> I can think of
> X) Never calling it twice within printf , but that will go wrong one
> day ...
> X) Making a dynamic allocation instead of a static buffer. But then
> deallocation must be systematically done for avoiding leaks ...
> (cumbersome)
>
> Other suggestions ?


Try:

int main(void) {
printf("%s ", Convert(10));
printf("%s\n", Convert(56));
return 0;
}

and now you know the sequence of calls to Convert.

Notice that main returns an int. Say and do so. The only int
values allowed are 0 or EXIT_SUCCESS or EXIT_FAILURE from stdlib.h

--
Chuck F ((E-Mail Removed)) ((E-Mail Removed))
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!


 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      08-15-2003
Eric Sosman wrote:
> Jos De Laender wrote:
>
> > [...]

>
> I once implemented a similar function that had a small
> array of static buffers and used them cyclically. That
> let me call the function multiple times within a single
> printf(), so long as I didn't call it more times than the
> function had buffers. (Yes, Your Honor, I know it was wrong.
> But I was in a hurry, and it was throw-away code, and I swear
> I'll never do it again, and I throw myself on the mercy of
> the Court. Aren't you up for re-electon soon?)


I have done the equivalent, and I don't consider it an evil
practice. In my case it served the purpose of supplying fixed
string arguments while keeping the strings in a separate
(editable) file and not using unavailable program memory space.
The implementation was via a special preprocessing run, so the
source looked totally normal.

Think of it as Garbage Collection, with a defined cycle time.

--
Chuck F ((E-Mail Removed)) ((E-Mail Removed))
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!


 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      08-15-2003
Jos De Laender wrote:
> Eric Sosman wrote:
> > Jos De Laender wrote:
> >

.... snip ...
> >
> > I once implemented a similar function that had a small
> > array of static buffers and used them cyclically. That
> > let me call the function multiple times within a single
> > printf(), so long as I didn't call it more times than the
> > function had buffers. (Yes, Your Honor, I know it was wrong.
> > But I was in a hurry, and it was throw-away code, and I swear
> > I'll never do it again, and I throw myself on the mercy of
> > the Court. Aren't you up for re-electon soon?)

>
> Good suggestion after all.
>
> My code will have thousands of those calls. So I'm really
> looking for a solution where caller doesn't have to bother
> about buffers and cleanup. And I know for sure - this is God
> told me in person - that there will be no printf with more
> than 5 of those calls to Convert.


You make convert auto initialize the buffers. Define a buffer as
a structure with a pointer to the next, and a pointer to the data
string. Keep a static pointer to a buffer. When convert is
called and finds that pointer NULL it knows it is initialization
time. It then creates a circular chained list of buffers, each of
which contains a different data pointer, which you get via
malloc. You control the number of buffers and size of the data
field here (God is fallible). Now the static pointer is no longer
NULL.

At each call to convert the static pointer is advanced via the
next field, and the data field is used as needed. Convert returns
the pointer to that data field.

--
Chuck F ((E-Mail Removed)) ((E-Mail Removed))
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
fprintf(fp,Count); gives C2664 error Joy2006 C++ 2 05-26-2006 05:48 AM
Equivalent of fprintf's -20.15g formatting with C++ formatted streams ? Koen C++ 1 10-05-2004 01:53 PM
debug assertion failed str!=NULL fprintf.c Arti Potnis C++ 2 09-02-2004 05:05 PM
fprintf() C variables into FORTRAN input file format ??? google C Programming 5 04-13-2004 02:49 PM
formatting float variables to fprintf function hpy_awad@yahoo.com C Programming 2 01-02-2004 06:28 AM



Advertisments