Thread: [GD-Windows] sprintf weirdness
Brought to you by:
vexxed72
From: Andras B. <bn...@ma...> - 2004-07-15 05:15:02
|
Hi, In a normal app, when I write this: sprintf(buf, "%.3f", 0.05f); the contents of buf will be "0.050". But in my app, the result is "0." instead!! The magic barrier seems to be 0.1, as numbers above that (or below -0.1) work OK. Now how's that? Is this a denormal issue?? 0.1 is quite big, isn't it? Still, I suspect that the problem lies in me having my own crt0 (don't ask why :) but I believe I do all the floating point initializations that the original crt0 does (it calls _fpmath(1); or (*_Fpinit)(1); whichever is defined somewhere (which btw only sets the FPU control word AFAICT), but it's still not working the way it should... What is happening here?? I've tried to trace sprintf, but in the end it just uses a function called _cfltcvt, which is totally undocumented and the only thing I could do is reverse engineer the assembly code, which I'd rather not do.. Any ideas what's causing this behavior?? Thanks, Andras |
From: Colin F. <cp...@ea...> - 2004-07-15 08:50:41
|
> Any ideas what's causing this behavior?? Could it be your "own crt0"? Hee, hee! But seriously: (1) Could it be that "buf" is somehow corrupted before you check its contents? Maybe try the following: sprintf( buf, "Hey!-->%.3f<--Look!", 0.05f ); (making sure "buf" can handle the extra text) and see that the stuff before and after the floating-point field appears in "buf" as expected. (2) Try out the following code from MSDN -- perhaps changing "_fcvt" to "_cfltcvt" as a wild guess if it fails to link with your crt0. Maybe testing cases similar to your 0.05f case with this function in particular will narrow down the problem. /* FCVT.C: This program converts the constant * 3.1415926535 to a string and sets the pointer * *buffer to point to that string. */ #include <stdlib.h> #include <stdio.h> void main( void ) { int decimal, sign; char *buffer; double source = 3.1415926535; buffer = _fcvt( source, 7, &decimal, &sign ); printf( "source: %2.10f buffer: '%s' decimal: %d sign: %d\n", source, buffer, decimal, sign ); } // Output // source: 3.1415926535 buffer: '31415927' decimal: 1 sign: 0 (3) Maybe put a memory breakpoint on "buf" to see when and how it is modified. Perhaps you'll find some unexpected modifications shortly AFTER your sprintf() call, and BEFORE your examination of the result. (4) Finally, I don't want to raise any undue panic, but you might be having psychotic hallucinations. It goes without saying that you are using your own crt0 on the advice of the voices in your head, but the question is whether or not your paranoia has you believing that space aliens tampered with your private crt0 to keep you from learning more than "0." -- after all, knowing the full value, 0.050, would expose the horrifying conspiracy. For sure the sys admins of your region of the Matrix would have to change some parameters to restore balanced gameplay. |
From: Andras B. <bn...@ma...> - 2004-07-15 17:51:42
|
> (1) Could it be that "buf" is somehow corrupted before you check its > contents? Maybe try the following: > > sprintf( buf, "Hey!-->%.3f<--Look!", 0.05f ); > > (making sure "buf" can handle the extra text) and see that the > stuff before and after the floating-point field appears in "buf" > as expected. Tried that, and it's not corrupted (I can see the "Hey" "Look!" messages in buf, but it's still "0." In the middle). > (2) Try out the following code from MSDN -- perhaps changing "_fcvt" > to "_cfltcvt" as a wild guess if it fails to link with your crt0. > Maybe testing cases similar to your 0.05f case with this function > in particular will narrow down the problem. > > /* FCVT.C: This program converts the constant > * 3.1415926535 to a string and sets the pointer > * *buffer to point to that string. > */ > > #include <stdlib.h> > #include <stdio.h> > > void main( void ) > { > int decimal, sign; > char *buffer; > double source = 3.1415926535; > > buffer = _fcvt( source, 7, &decimal, &sign ); > printf( "source: %2.10f buffer: '%s' decimal: %d sign: %d\n", > source, buffer, decimal, sign ); > } > > // Output > // source: 3.1415926535 buffer: '31415927' decimal: 1 sign: 0 _fcvt seems to work fine! Strange! So what does that mean? > (3) Maybe put a memory breakpoint on "buf" to see when and how it is > modified. Perhaps you'll find some unexpected modifications > shortly AFTER your sprintf() call, and BEFORE your examination > of the result. Actually, I did step through printf, until the call of that _cfltcvt, when the result immediately appeared in the buffer, so the only thing that could screw up is _cfltcvt... > (4) Finally, I don't want to raise any undue panic, but you might > be having psychotic hallucinations. It goes without saying that > you are using your own crt0 on the advice of the voices in your head, > but the question is whether or not your paranoia has you believing > that space aliens tampered with your private crt0 to keep you > from learning more than "0." -- after all, knowing the full > value, 0.050, would expose the horrifying conspiracy. For sure > the sys admins of your region of the Matrix would have to change > some parameters to restore balanced gameplay. I have hallucinations all the time! I feel dizzy, and my eyes project words into my brain written by some guy called Colin.. but I don't think he really exists. I think he's just a helper bot installed into our brains (hmm, maybe he's responsible for my recent memory leaks? I really need a decent garbage collector!). Anyway, I don't fear the aliens, and I won't let them mess with my crt0!! Cheers, Andras |
From: Javier A. <ja...@py...> - 2004-07-15 09:00:47
|
Andras Balogh wrote: > Now how's that? Is this a denormal issue?? 0.1 is quite big, isn't it? > Still, I suspect that the problem lies in me having my own crt0 > (don't ask why :) Yes it's very likely that your problem originates in your own crt0. > but I believe I do all the floating point > initializations that the original crt0 does (it calls _fpmath(1); or > (*_Fpinit)(1); whichever is defined somewhere (which btw only sets > the FPU control word AFAICT), but it's still not working the way it > should... What is happening here?? Can you verify that the control word generated by your crt0 is IDENTICAL to the one generated by the standard crt? All bets are that's not the case. sprintf() works under a number of assumptions about the state of the run-time. I believe the source code is available, so you can check which assumptions are those, and whether you comply with them or not. -- Javier Arevalo Pyro Studios |
From: Andras B. <bn...@ma...> - 2004-07-15 17:51:41
|
> Can you verify that the control word generated by your crt0 is IDENTICAL > to > the one generated by the standard crt? All bets are that's not the case. Yes, I've called _control87(0, 0) right before printf on both a standard app, and mine, and they returned the same result.. > sprintf() works under a number of assumptions about the state of the > run-time. I believe the source code is available, so you can check which > assumptions are those, and whether you comply with them or not. Yeah, the source code is available, but it uses the magic _cfltcvt, for which I have nothing... The funny thing is, that when the number is exactly 0, it prints "0.000" It only fails, when 0 < abs(x) < 0.1 Thanks, Andras |
From: Andras B. <bn...@ma...> - 2004-07-15 19:56:09
|
Ok, I've found the bug: I've had my own memset routine, and my version of memset uses the int pattern as a 32 bit value to fill the memory, while the original memset uses only the first byte of the int pattern to fill... Now how funny is that! :-) Cheers, Andras |