473,473 Members | 1,555 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

My error or fprintf implementation error ?

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
Nov 13 '05 #1
7 2995
Jos De Laender <Jo************@pandora.be> 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
--
_ _____ _____
| ||_ _||_ _| Je***********@physik.fu-berlin.de
_ | | | | | |
| |_| | | | | | http://www.physik.fu-berlin.de/~toerring
\___/ens|_|homs|_|oerring
Nov 13 '05 #2
Jos De Laender <Jo************@Pandora.Be> 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
Nov 13 '05 #3
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
Nov 13 '05 #4
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.

--
Er*********@sun.com

Nov 13 '05 #5
Jos De Laender wrote:
Je***********@physik.fu-berlin.de wrote:
Jos De Laender <Jo************@pandora.be> 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 (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 13 '05 #6
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 (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 13 '05 #7
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 (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 13 '05 #8

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

Similar topics

1
by: yanwan | last post by:
Hello I am now compling a project, but in one source file of this project, I met this problem. It seems very strange. Below is this source file: ----------------------------------------...
1
by: Patrick Dunnigan | last post by:
Hi, I am attempting a bulk copy from a c program into SQL Server 2000 using DBLib in freeTDS 0.63 RC11 (gcc 3.4.3, RH 9). I am getting an error message that I cannot find any documentation on. ...
6
by: Rick | last post by:
Hi, Sorry, I couldn't find a better title for this post. Anyway, I got a piece of C code which only works well if I put a fprintf in it. Here's the code : unsigned int8 Port_getPortNum( char...
4
by: yanwan | last post by:
Hello I am now compling a project, but in one source file of this project, I met this problem. It seems very strange. Below is this source file: ----------------------------------------...
14
by: Marlene Stebbins | last post by:
At one point in my program I have about a dozen calls to malloc. I want to check for malloc failure, but I don't want to write: if((buffer_x = malloc(BUFSIZE * sizeof(*buffer_x))) == NULL) {...
21
by: one2001boy | last post by:
PostMessage() function returns ERROR_NOT_ENOUGH_QUOTA after running in a loop for 700 times, but the disk space and memory are still big enough. any suggestion to resolve this problem? thanks.
10
by: eastcoastguyz | last post by:
(I've not done C prorgamming in such a long time, I have forgotten how to do this.) I'm writing a program, where it fopens a file with "a+", and I want to be able to continue writing to this...
12
by: jonatan | last post by:
Hello All, I am making a program and need the grt_main.c but i try to compile have the error c1004.Please help me how to solve it? Thank you. --------------------Configuration: pre - Win32...
16
by: wizard | last post by:
Here is a piece of code below for writing and reading blobs in SQLITE database. I ' ve a problem to read from blob struct called 'Points' Any help would be appreciated Reagards Greg ...
9
by: arnuld | last post by:
Can anyone point me to some online/offline document on error handling in C ? I am doing some Socket Programming in C and feeling a lots of difficult in error handling :( Also some time ago...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?

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.