EmbeddedRelated.com
Forums

Linux printf funny

Started by Paul Burke February 27, 2007
I'm converting an application from Windows console to Linux, and the 
changeover has gone remarkably easily (considering that I know very 
little about Linux), until now.

No problem installing GCC, KDevelop, FTDI USB drivers, remarkably few 
changes to recompile the code... but printf fails after about 
half-a-dozen calls. A float value prints as "nan"- not a number I asume, 
rather than what I eat with an Indian takeout. This value is computed 
from two int values (actually a weight and a tare reading) and 
multiplied by a scale factor (1.0 for the tests).

The funny thing is that I can't see anything different about the weight 
or the tare value between instances that print and those that fail. 
There is the expected one-or-two bits wobble in the weight reading, but 
the values only oscillate between plus and minus one relative to the 
tare. Once it fails, it seems to be sticky- it doesn't recover even when 
the readings are identical to before the nan.

So, please you Linux/ GCC experienced people- what absolutely basic item 
of knowledge am I lacking?

Paul Burke
In comp.arch.embedded,
Paul Burke <paul@scazon.com> wrote:
> I'm converting an application from Windows console to Linux, and the > changeover has gone remarkably easily (considering that I know very > little about Linux), until now. >
Is this a win32 console application or an old DOS application?
> No problem installing GCC, KDevelop, FTDI USB drivers, remarkably few > changes to recompile the code... but printf fails after about > half-a-dozen calls. A float value prints as "nan"- not a number I asume, > rather than what I eat with an Indian takeout. This value is computed > from two int values (actually a weight and a tare reading) and > multiplied by a scale factor (1.0 for the tests). > > The funny thing is that I can't see anything different about the weight > or the tare value between instances that print and those that fail. > There is the expected one-or-two bits wobble in the weight reading, but > the values only oscillate between plus and minus one relative to the > tare. Once it fails, it seems to be sticky- it doesn't recover even when > the readings are identical to before the nan. > > So, please you Linux/ GCC experienced people- what absolutely basic item > of knowledge am I lacking?
It does not sound like a windows/linux problem, but more like a programming error. So please show us the code. I know I found some errors in old DOS (turbo C) test programs when I ported them to new versions of compilers (windows or linux). These programs worked normally using the old compiler but failed using a newer one. All the errors where my own (beginners)fault: uninitialized vars, wrong format specifiers, near/far pointer stuff etc. -- Stef (remove caps, dashes and .invalid from e-mail address to reply by mail)
Stef wrote:
>>> > Is this a win32 console application or an old DOS application? >
It was W32 console, compiled with VC++6.
> > It does not sound like a windows/linux problem, but more like a > programming error. So please show us the code. >
#include <stdint.h> #include <stdlib.h> #include <stdio.h> #include <math.h> #include <string.h> #include "WinTypes.h" #include "ftd2xx.h" #include "ADC.h" int TareWeight = 0; // ADC reading at no- load double ScaleFactor = 1.0; // Bridge scale factor double ReadWeight(void) { char buff[100]; double fweight; // Float version of weight int Weight; // Weight as returned by ADC Weight= ADCConvert(); fweight= (double)(Weight - TareWeight) * ScaleFactor; sprintf( buff, "%08x - %08x -> %9.3f", Weight, TareWeight, fweight); MessageBox( 0,buff,"Conversion Result",0); return fweight; } MessageBox() is just a function that displays the strings supplied, and is in fact a replacement for the Windows message box as in the program's earlier incarnation as a windows GUI program before it got converted to console (don't ask!). Here's the console output: Conversion Result 000087bf - 000087bf -> 0.000 Conversion Result 000087bf - 000087bf -> 0.000 Conversion Result 000087bf - 000087bf -> 0.000 Conversion Result 000087bf - 000087bf -> 0.000 Conversion Result 000087c0 - 000087bf -> 1.000 Conversion Result 000087bf - 000087bf -> 0.000 Conversion Result 000087c0 - 000087bf -> 1.000 Conversion Result 000087bf - 000087bf -> nan Conversion Result 000087c0 - 000087bf -> nan Conversion Result 000087bf - 000087bf -> nan "nan" then remains sticky until I restart the program. You'll notice that the int readings are much the same as when the output is correct!
> I know I found some errors in old DOS (turbo C) test programs when I > ported them to new versions of compilers (windows or linux). These > programs worked normally using the old compiler but failed using a > newer one. All the errors where my own (beginners)fault: uninitialized > vars, wrong format specifiers, near/far pointer stuff etc. >
I could believe that better if it didn't work for the first few readings. Paul Burke
"Paul Burke" <trash@scazon.com> wrote in message 
news:54iq2sF216i72U1@mid.individual.net...
> Stef wrote: >>>> >> Is this a win32 console application or an old DOS application? >> > > It was W32 console, compiled with VC++6. > >> >> It does not sound like a windows/linux problem, but more like a >> programming error. So please show us the code. >> > > #include <stdint.h> > #include <stdlib.h> > #include <stdio.h> > #include <math.h> > #include <string.h> > > #include "WinTypes.h" > #include "ftd2xx.h" > #include "ADC.h" > > int TareWeight = 0; // ADC reading at no- load > double ScaleFactor = 1.0; // Bridge scale factor > > double ReadWeight(void) > { > char buff[100]; > double fweight; // Float version of weight > int Weight; // Weight as returned by ADC > > Weight= ADCConvert(); > > fweight= (double)(Weight - TareWeight) * ScaleFactor; > sprintf( buff, "%08x - %08x -> %9.3f", Weight, TareWeight, fweight); > MessageBox( 0,buff,"Conversion Result",0); > return fweight; > } >
If I was a betting man (which I'm not) then I'd say ScaleFactor is being corrupted somewhere else. Clearly TareWeight doesn't stay 0 either. So, what changes them? [snip] Peter
Peter Dickerson wrote:

> > If I was a betting man (which I'm not) then I'd say ScaleFactor is being > corrupted somewhere else. Clearly TareWeight doesn't stay 0 either. So, what > changes them? >
TareWeight is set (in this rather attenuated version of the program) by the first read of the ADC on startup. Scale factor is a constant (i.e. I've taken out the bit that changes it) while I'm getting the basics going with the changed OS. Paul Burke
Paul Burke <paul@scazon.com> writes:
> So, please you Linux/ GCC experienced people- what absolutely basic > item of knowledge am I lacking?
How to use the debugger ;-) Run your app under gdb, put a hardware watchpoint on your variables, and see when they change. Or at least put a breakpoint after the printf, continue until it reads nan, and inspect all the variables to see which one is wrong (if any). Sometimes, you can't use just printf to debug code. If you can't use gdb to inspect the variables, write a routine to hex-dump them (i.e. cast their address to unsigned char *, dump sizeof(var) bytes), and call it from various places to try to track down what's happening.
Op Tue, 27 Feb 2007 14:22:24 +0100 schreef Paul Burke <trash@scazon.com>=
:
> Stef wrote: >> It does not sound like a windows/linux problem, but more like a >> programming error. So please show us the code. >> > > #include <stdint.h> > #include <stdlib.h> > #include <stdio.h> > #include <math.h> > #include <string.h> > > #include "WinTypes.h" > #include "ftd2xx.h" > #include "ADC.h" > > int TareWeight =3D 0; // ADC reading at no- load > double ScaleFactor =3D 1.0; // Bridge scale factor > > double ReadWeight(void) > { > char buff[100]; > double fweight; // Float version of weight > int Weight; // Weight as returned by ADC > > Weight=3D ADCConvert(); > > fweight=3D (double)(Weight - TareWeight) * ScaleFactor; > sprintf( buff, "%08x - %08x -> %9.3f", Weight, TareWeight, fweight); > MessageBox( 0,buff,"Conversion Result",0); > return fweight; > } > > > > MessageBox() is just a function that displays the strings supplied, an=
d =
> is in fact a replacement for the Windows message box as in the program=
's =
> earlier incarnation as a windows GUI program before it got converted t=
o =
> console (don't ask!). > > Here's the [modified] console output: > > 000087bf - 000087bf -> 0.000 > 000087bf - 000087bf -> 0.000 > 000087bf - 000087bf -> 0.000 > 000087bf - 000087bf -> 0.000 > 000087c0 - 000087bf -> 1.000 > 000087bf - 000087bf -> 0.000 > 000087c0 - 000087bf -> 1.000 > 000087bf - 000087bf -> nan > 000087c0 - 000087bf -> nan > 000087bf - 000087bf -> nan > > "nan" then remains sticky until I restart the program. You'll notice =
> that the int readings are much the same as when the output is correct!=
Looks like an optimization problem. The compiler is seeing a constant = where it shouldn't, and/or has modified the type of a variable to double= . = Without seeing the code that deals with TareWeight, I'd guess this is it= . = Try making it volatile. Another possibility is a bug that modifies ScaleFactor, which BTW isn't = = declared const.
>> I know I found some errors in old DOS (turbo C) test programs when I >> ported them to new versions of compilers (windows or linux). These >> programs worked normally using the old compiler but failed using a >> newer one. All the errors where my own (beginners)fault: uninitialize=
d
>> vars, wrong format specifiers, near/far pointer stuff etc. > > I could believe that better if it didn't work for the first few readin=
gs. Floating point types have the property that they can 'saturate' to NaN's= , = Infinities or Zeroes over successive calculations. Some compilers have = a = "strict math(s)" option to reduce that effect. -- = Gemaakt met Opera's revolutionaire e-mailprogramma: = http://www.opera.com/mail/
Paul Burke wrote:
> Stef wrote: >>>> >> Is this a win32 console application or an old DOS application? >> > > It was W32 console, compiled with VC++6. > >> >> It does not sound like a windows/linux problem, but more like a >> programming error. So please show us the code. >> > > #include <stdint.h> > #include <stdlib.h> > #include <stdio.h> > #include <math.h> > #include <string.h> > > #include "WinTypes.h"
If this is what I believe it is, you should find a way to remove it. I'm not sure it does any harm, but when trying to find arcane errors you'd better go with the safest and most standard setup.
> #include "ftd2xx.h" > #include "ADC.h" > > int TareWeight = 0; // ADC reading at no- load > double ScaleFactor = 1.0; // Bridge scale factor > > double ReadWeight(void) > { > char buff[100]; > double fweight; // Float version of weight > int Weight; // Weight as returned by ADC > > Weight= ADCConvert(); > > fweight= (double)(Weight - TareWeight) * ScaleFactor;
Would the C promotions get in the way somehow? It shouldn't, but I'm still wondering about it.
> sprintf( buff, "%08x - %08x -> %9.3f", Weight, TareWeight, fweight); > MessageBox( 0,buff,"Conversion Result",0);
Safest setup again here: printf("Conversion result: %08x - %08x -> %9.3f", Weight, TareWeight, fweight);
> return fweight; > } > > > > MessageBox() is just a function that displays the strings supplied, and > is in fact a replacement for the Windows message box as in the program's > earlier incarnation as a windows GUI program before it got converted to > console (don't ask!). > > Here's the console output: > > Conversion Result > 000087bf - 000087bf -> 0.000 > Conversion Result > 000087bf - 000087bf -> 0.000 > Conversion Result > 000087bf - 000087bf -> 0.000 > Conversion Result > 000087bf - 000087bf -> 0.000 > Conversion Result > 000087c0 - 000087bf -> 1.000 > Conversion Result > 000087bf - 000087bf -> 0.000 > Conversion Result > 000087c0 - 000087bf -> 1.000 > Conversion Result > 000087bf - 000087bf -> nan > Conversion Result > 000087c0 - 000087bf -> nan > Conversion Result > 000087bf - 000087bf -> nan > > "nan" then remains sticky until I restart the program. You'll notice > that the int readings are much the same as when the output is correct! > >> I know I found some errors in old DOS (turbo C) test programs when I >> ported them to new versions of compilers (windows or linux). These >> programs worked normally using the old compiler but failed using a >> newer one. All the errors where my own (beginners)fault: uninitialized >> vars, wrong format specifiers, near/far pointer stuff etc. >> > > I could believe that better if it didn't work for the first few readings. > > Paul Burke
Nan is usually because there is an error such a the root of a negative number, or infinity, or things like that. Which is pretty strange given your calculations... You could try things such as: float ScaleFactor = 1.0; To try to avoid needing more accuracy than what a double (fweight) can represent. Is ScaleFactor modified somehow somewhere else in the code? And which compiler to which target are you using? Regards, D.

Paul Burke wrote:

> I'm converting an application from Windows console to Linux, and the > changeover has gone remarkably easily (considering that I know very > little about Linux), until now. > > No problem installing GCC, KDevelop, FTDI USB drivers, remarkably few > changes to recompile the code... but printf fails after about > half-a-dozen calls.
If it is a multithreaded application, this can be the issue with printf() reentrancy. Many of the stdio.h functions are not reentrant by default, unless you are linking the appropriate libraries. Vladimir Vassilevsky DSP and Mixed Signal Design Consultant http://www.abvolt.com
Vladimir Vassilevsky <antispam_bogus@hotmail.com> wrote:
> If it is a multithreaded application, this can be the issue with > printf() reentrancy. Many of the stdio.h functions are not reentrant by > default, unless you are linking the appropriate libraries.
..yes you need to pass "-pthread" to GCC which has the effect of defining _REENTRANT and linking against libpthread. This is documented as required on some platforms but strangely not for x86 I don't know if this is a long standing oversight or if it really isn't needed. -p -- "Unix is user friendly, it's just picky about who its friends are." - Anonymous --------------------------------------------------------------------