By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,436 Members | 2,979 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,436 IT Pros & Developers. It's quick & easy.

problems with sprintf...

P: n/a
Hi all....

I have a little problem that's driving me nuts. I can't seem to make any
sense of it. I have this small webserver that substitutes some data from a
page when finds a substitution string. I all works fine, even the sprintf,
when I write numbers. But if I want to write a character string, it all goes
wrong.
I am trying to print "over" on the pointer Key on a function that looks
like this (this is only an extract of the real one, which is much larger).
While I print floats or integers there's no problem, even if I write a small
string with a couple characters like "/bm" works fine. But when I get to the
case 'c' it displays a 5 digit number, always the same, and then my string.
unsigned char *Key;
unsigned char NewKey[25];
unsigned int i;

if (TCPTxDataCount < 4) return;

Key = TCP_TX_BUF;

for (i = 0; i < (TCPTxDataCount - 2); i++)
{
if (*Key == '¿')
{
if (*(Key + 1) == '?')
{
switch (*(Key + 2))
{
case 'a' :
{
sprintf(NewKey, "%4.2f", Func_returning_a_float());
memcpy(Key, NewKey, 5);
break;
}
case 'b' :
{
if (Get_conditional_function() == 0xAFAF)
{
sprintf(NewKey, "%4.3f", Float_number_1());
memcpy(Key, NewKey, 4);
break;
}
else
{
sprintf(NewKey, "%4.3f%s", float_num_2(), "/bm");
memcpy(Key, NewKey, 7);
break;
}
/* up until here it all works smoothly. */
case 'c' :
{
sprintf(NewKey, "%s", "over");
memcpy(Key, NewKey, 4);
break;
}

/* if I reset the amount of data to be copied to Key from 4 to, lets say,
20, I get a 7 digit number, always the same, and then my string....
something like: "20.7570over"
Any idea of what's going on? I thought I was using sprintf correctly, but it
seems it doesn't want to work with characters....
Cheers!

Yodai



Nov 14 '05 #1
Share this Question
Share on Google+
13 Replies


P: n/a
If someone sees the problem and feels like answering, feel free. But I
arranged the problem changing the switch caracters. I still don't know what
was failing, but I had one of those lucky strikes
I-don't-know-how-I-did-it-but-it-works....

Yodai
"Yodai" <yo***@spamnot.mail.vu> escribió en el mensaje
news:sw***********************@telenews.teleline.e s...
Hi all....

I have a little problem that's driving me nuts. I can't seem to make any
sense of it. I have this small webserver that substitutes some data from a
page when finds a substitution string. I all works fine, even the sprintf,
when I write numbers. But if I want to write a character string, it all goes wrong.
I am trying to print "over" on the pointer Key on a function that looks
like this (this is only an extract of the real one, which is much larger).
While I print floats or integers there's no problem, even if I write a small string with a couple characters like "/bm" works fine. But when I get to the case 'c' it displays a 5 digit number, always the same, and then my string.

unsigned char *Key;
unsigned char NewKey[25];
unsigned int i;

if (TCPTxDataCount < 4) return;

Key = TCP_TX_BUF;

for (i = 0; i < (TCPTxDataCount - 2); i++)
{
if (*Key == '¿')
{
if (*(Key + 1) == '?')
{
switch (*(Key + 2))
{
case 'a' :
{
sprintf(NewKey, "%4.2f", Func_returning_a_float());
memcpy(Key, NewKey, 5);
break;
}
case 'b' :
{
if (Get_conditional_function() == 0xAFAF)
{
sprintf(NewKey, "%4.3f", Float_number_1());
memcpy(Key, NewKey, 4);
break;
}
else
{
sprintf(NewKey, "%4.3f%s", float_num_2(), "/bm");
memcpy(Key, NewKey, 7);
break;
}
/* up until here it all works smoothly. */
case 'c' :
{
sprintf(NewKey, "%s", "over");
memcpy(Key, NewKey, 4);
break;
}

/* if I reset the amount of data to be copied to Key from 4 to, lets say,
20, I get a 7 digit number, always the same, and then my string....
something like: "20.7570over"
Any idea of what's going on? I thought I was using sprintf correctly, but it seems it doesn't want to work with characters....
Cheers!

Yodai


Nov 14 '05 #2

P: n/a
On Tue, 13 Jan 2004 10:12:40 GMT,
Yodai <yo***@spamnot.mail.vu> wrote
in Msg. <sw***********************@telenews.teleline.es>
Hi all....

I have a little problem that's driving me nuts. I can't seem to make any
sense of it. I have this small webserver that substitutes some data from a
page when finds a substitution string. I all works fine, even the sprintf,
when I write numbers. But if I want to write a character string, it all goes
wrong.
While I can't see right away what causes your code to behave the way it
does, here a few tips:

1) When using sprintf() you run the risk of buffer overflow unless you
can make absolutely sure that no possible argument value can cause an
overflow. It's better to use snprintf() if you have it.

2) The string literal "over" requires 5 bytes, not 4 (but that doesn't
seem to be your problem here). Related note: Replace the calls to memcpy
with strcpy which always takes care of the trailing zero. And make sure
that Key is big enouch to hold the data *in all cases*.
string with a couple characters like "/bm" works fine. But when I get to the
case 'c' it displays a 5 digit number, always the same, and then my string.
What does 'it displays' mean? There is no code in your snippet that
displays anything. The code you posted seems to put the right thing into
NewKey, but NewKey might get corrupted someplace else.

You're experiencing a classic case of Undefined Behaviour. The more
difficult it is to track the mistake, the more embarrasing it usually is
when you finally find it ;-)
case 'c' :
{
sprintf(NewKey, "%s", "over");
memcpy(Key, NewKey, 4);
break;
}
Any idea of what's going on? I thought I was using sprintf correctly, but it
seems it doesn't want to work with characters....


Just for giggles... Have you tried strcpy(Key, "over")? Should accomplish
the exact same thing. But yes, you're using sprintf correctly.

--Daniel

--
"With me is nothing wrong! And with you?" (from r.a.m.p)
Nov 14 '05 #3

P: n/a
On Tue, 13 Jan 2004 10:33:47 GMT,
Yodai <yo***@spamnot.mail.vu> wrote
in Msg. <fQ***********************@telenews.teleline.es>
If someone sees the problem and feels like answering, feel free. But I
arranged the problem changing the switch caracters. I still don't know what
was failing, but I had one of those lucky strikes
I-don't-know-how-I-did-it-but-it-works....


I'm tempted to think that you're still having UB, only now it happens to
behave the way you expect... for a while... until you change something
someplace and everything goes haywire again.

Has happened many times to me (and to everybody else on this ng, I
daresay).

--Daniel

--
"With me is nothing wrong! And with you?" (from r.a.m.p)
Nov 14 '05 #4

P: n/a
In <sw***********************@telenews.teleline.es> "Yodai" <yo***@spamnot.mail.vu> writes:
I am trying to print "over" on the pointer Key on a function that looks
like this (this is only an extract of the real one, which is much larger).
While I print floats or integers there's no problem, even if I write a small
string with a couple characters like "/bm" works fine. But when I get to the
case 'c' it displays a 5 digit number, always the same, and then my string.
unsigned char *Key;
unsigned char NewKey[25];
unsigned int i;

if (TCPTxDataCount < 4) return;

Key = TCP_TX_BUF;

for (i = 0; i < (TCPTxDataCount - 2); i++)
{
if (*Key == '¿')
{
if (*(Key + 1) == '?')
{
switch (*(Key + 2))
{
case 'a' :
{
sprintf(NewKey, "%4.2f", Func_returning_a_float());
memcpy(Key, NewKey, 5);
break;
}
case 'b' :
{
if (Get_conditional_function() == 0xAFAF)
{
sprintf(NewKey, "%4.3f", Float_number_1());
memcpy(Key, NewKey, 4);
break;
}
else
{
sprintf(NewKey, "%4.3f%s", float_num_2(), "/bm");
memcpy(Key, NewKey, 7);
break;
}
/* up until here it all works smoothly. */
case 'c' :
{
sprintf(NewKey, "%s", "over");
memcpy(Key, NewKey, 4);
break;
}

/* if I reset the amount of data to be copied to Key from 4 to, lets say,
20, I get a 7 digit number, always the same, and then my string....
something like: "20.7570over"
Any idea of what's going on? I thought I was using sprintf correctly, but it
seems it doesn't want to work with characters....


I suspect the problem is memory corruption occuring elsewhere in your
program. Put the above code into the main function, along with the
missing bits necessary to turn it into a complete program and see what
happens.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #5

P: n/a
Yup.... but I just found the reason... It belonged to another part of the
program where I was forcing to execute 2 different switch under the same
if,else, giving only once the instruction key++, thus, only allowing one of
my switch to advance forward.....

Cheers...

Yodai
Nov 14 '05 #6

P: n/a
"Yodai" <yo***@spamnot.mail.vu> wrote in message news:<sw***********************@telenews.teleline. es>...
Hi all....

I have a little problem that's driving me nuts. I can't seem to make any
sense of it. I have this small webserver that substitutes some data from a
page when finds a substitution string. I all works fine, even the sprintf,
when I write numbers. But if I want to write a character string, it all goes
wrong.
I am trying to print "over" on the pointer Key on a function that looks
like this (this is only an extract of the real one, which is much larger).
While I print floats or integers there's no problem, even if I write a small
string with a couple characters like "/bm" works fine. But when I get to the
case 'c' it displays a 5 digit number, always the same, and then my string.
unsigned char *Key;
unsigned char NewKey[25];
unsigned int i;

if (TCPTxDataCount < 4) return;

Key = TCP_TX_BUF;

for (i = 0; i < (TCPTxDataCount - 2); i++)
{
if (*Key == '¿')
{
if (*(Key + 1) == '?')
{
switch (*(Key + 2))
{
case 'a' :
{
sprintf(NewKey, "%4.2f", Func_returning_a_float());
memcpy(Key, NewKey, 5);
break;
}
case 'b' :
{
if (Get_conditional_function() == 0xAFAF)
{
sprintf(NewKey, "%4.3f", Float_number_1());
memcpy(Key, NewKey, 4);
break;
}
else
{
sprintf(NewKey, "%4.3f%s", float_num_2(), "/bm");
memcpy(Key, NewKey, 7);
break;
}
/* up until here it all works smoothly. */
case 'c' :
{
sprintf(NewKey, "%s", "over");
memcpy(Key, NewKey, 4);
break;
}

/* if I reset the amount of data to be copied to Key from 4 to, lets say,
20, I get a 7 digit number, always the same, and then my string....
something like: "20.7570over"
Any idea of what's going on? I thought I was using sprintf correctly, but it
seems it doesn't want to work with characters....
Cheers!

Yodai


You aren't allowing for copying the terminating NUL character with your
memcpy. To copy "over", you need to copy 5 bytes. Note that your
stringified floats will often not be copied in full, and the string
won't be terminated if they are not... %4.2f says minimum field
width 4, max precision of 2 digits after the decimal point.

e.g. 100.4567 -> sprintf("%4.2f",...) -> 100.45

Which takes 7 bytes as a string... If you aren't worried
about efficiency you could use strcpy, though you then must make
sure you don't exceed the bounds of your target array. Or you
could use snprintf if you have C99/compiler extensions to
restrict the number of bytes in the string. From the code above,
you also could perhaps sprintf straight into your Key as well.

-David
Nov 14 '05 #7

P: n/a
"David Resnick" <ln********@hotmail.com> wrote in message
news:59**************************@posting.google.c om...
Note that your stringified floats will often not be copied in full,
and the string won't be terminated if they are not...


sprintf() never creates an unterminated string.
Nov 14 '05 #8

P: n/a
Yodai wrote:

Please don't top-post. Your replies belong following properly trimmed
quotes.
If someone sees the problem and feels like answering, feel free. But I
arranged the problem changing the switch caracters. I still don't know what
was failing, but I had one of those lucky strikes
I-don't-know-how-I-did-it-but-it-works....

I don't know that I would call it lucky. You've been successful at
shotgun debugging.

shotgun debugging
n. The software equivalent of Easter egging; the making of relatively
undirected changes to software in the hope that a bug will be perturbed
out of existence. This almost never works, and usually introduces more
bugs.
You did manage to perturb your bug temporarily. However, rearranging
case elements is not likely to fix anything, just cover it up. The sort
of problem you describe, and the "fix" often points toward problems with
automatic storage, "whacking the stack" or some equivalent. Likely some
code is overwriting other elements. By changing the order, you change
with gets clobbered, and now it isn't the thing you could see before.

In some ways, you've gone from bad to worse. Before, you at least had an
indication that things were wrong and approximately where. Now it
probably lurking under the surface, waiting for you to make another
change or add something, so it can bite you in a new place.


Brian Rodenborn
Nov 14 '05 #9

P: n/a
On Tue, 13 Jan 2004 10:33:47 GMT, "Yodai" <yo***@spamnot.mail.vu>
wrote:
If someone sees the problem and feels like answering, feel free. But I
arranged the problem changing the switch caracters. I still don't know what
was failing, but I had one of those lucky strikes
I-don't-know-how-I-did-it-but-it-works....

No, it doesn't. It just misbehaves in a different way, that you
haven't seen yet. "Fixes" like this often produce programs which work
only until a customer uses them.

What you should do now is put the code back the way it was, and find
the real problem. Then look for the same problem in the rest of the
program, because you've probably done it more than once.

--
Al Balmer
Balmer Consulting
re************************@att.net
Nov 14 '05 #10

P: n/a
In <bu************@ID-149533.news.uni-berlin.de> "Alex" <me@privacy.net> writes:
"David Resnick" <ln********@hotmail.com> wrote in message
news:59**************************@posting.google. com...
Note that your stringified floats will often not be copied in full,
and the string won't be terminated if they are not...


sprintf() never creates an unterminated string.


But memcpy(), as used in the code under discussion, does.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #11

P: n/a
"Alex" <me@privacy.net> wrote in message news:<bu************@ID-149533.news.uni-berlin.de>...
"David Resnick" <ln********@hotmail.com> wrote in message
news:59**************************@posting.google.c om...
Note that your stringified floats will often not be copied in full,
and the string won't be terminated if they are not...


sprintf() never creates an unterminated string.


Yep, even if does a buffer overrun to do so. I wasn't saying that,
I was talking about the memcpy. If you memcpy part of a string generated
with sprintf, you won't get the termination...

-David
Nov 14 '05 #12

P: n/a
On Tue, 13 Jan 2004, Yodai wrote:
Hi all....

I have a little problem that's driving me nuts. I can't seem to make any
sense of it. I have this small webserver that substitutes some data from a
page when finds a substitution string. I all works fine, even the sprintf,
when I write numbers. But if I want to write a character string, it all goes
wrong.
I am trying to print "over" on the pointer Key on a function that looks
like this (this is only an extract of the real one, which is much larger).
While I print floats or integers there's no problem, even if I write a small
string with a couple characters like "/bm" works fine. But when I get to the
case 'c' it displays a 5 digit number, always the same, and then my string.
unsigned char *Key;
unsigned char NewKey[25];
unsigned int i;

if (TCPTxDataCount < 4) return;
What is the significance of 4 here? You might want to use a const or
something. If I had to take over your code I'd end up wasting a lot of
time figuring out little things like this.
Key = TCP_TX_BUF;

for (i = 0; i < (TCPTxDataCount - 2); i++)
The variable i is an unsigned int. Do you know what will happen if
TCPTxDataCount is 0, 1 or 2? What does i < -2 means when i is unsigned?
{
if (*Key == '¿')
Failed to see if Key is NULL before dereferencing it. If Key == NULL then
you want to abort this whole thing.
{
/* inside if statement #1 */
if (*(Key + 1) == '?')
{
/* inside if statement #2 */
switch (*(Key + 2))
{
/* inside switch statement */
case 'a' :
{
/* inside case a block */ sprintf(NewKey, "%4.2f", Func_returning_a_float());
memcpy(Key, NewKey, 5);
Why the magic number 5?
break;
}
/* outside case a block */
case 'b' :
{
/* inside case b block */
if (Get_conditional_function() == 0xAFAF)
{
/* inside if statement #3 */
sprintf(NewKey, "%4.3f", Float_number_1());
memcpy(Key, NewKey, 4);
break;
}
/* outside if statement #3 */
else
{

/* inside else statement associated with if #3 */
sprintf(NewKey, "%4.3f%s", float_num_2(), "/bm");
memcpy(Key, NewKey, 7);
Why the magic number 7?
break;
}
/* outside else statement, but still in case b */
/* up until here it all works smoothly. */
You are about to define case c but you have not closed off the case b
block.
case 'c' :
{
sprintf(NewKey, "%s", "over");
memcpy(Key, NewKey, 4);
Why the magic number 4?
break;
}

/* if I reset the amount of data to be copied to Key from 4 to, lets say,
20, I get a 7 digit number, always the same, and then my string....
something like: "20.7570over"
Maybe you are using memcpy wrong? If I have the data:

char NewKey[] = "over";

then the size of NewKey is 5. This is more obvious if I write it as:

char NewKey[] = { 'o', 'v', 'e', 'r', '\0' };
Any idea of what's going on? I thought I was using sprintf correctly, butit
seems it doesn't want to work with characters....


I saw your message indicating that the problem went away. If you don't
know why something was failing and why it started working again, then you
know nothing. It APPEARS to be working.

In real life development the odds of this attitude working are against
you. You do some testing and it looks like it works. Maybe one other
developers will test your code. Someone from integration and system
testing will look at it. Maybe even a dozen people will go over it during
the software development life cycle. We round up to the nearest 10 and say
that 20 people have tried it and it appears to work. You then release it
to the market and 10,000 people try it within the first week. I bet you
10,000 people using it will find that bug you are missing.

--
Send e-mail to: darrell at cs dot toronto dot edu
Don't send e-mail to vi************@whitehouse.gov
Nov 14 '05 #13

P: n/a
hey.! thank's for the post....... it WAS helpful.... I posted above the
solution to my problem which I finally found out....

Yodai
Nov 14 '05 #14

This discussion thread is closed

Replies have been disabled for this discussion.