Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!usc!zaphod.mps.ohio-state.edu!think.com!mintaka!bloom-picayune.mit.edu!news From: scs@adam.mit.edu (Steve Summit) Newsgroups: comp.lang.c Subject: Re: fscanf bug in TC (BC) C++ 2.0 Keywords: turbo C++ Message-ID: <1991Apr18.021515.1481@athena.mit.edu> Date: 18 Apr 91 02:15:15 GMT References: <1991Apr14.215819.16486@allgfx.agi.oz> <1991Apr16.141117.5065@odin.diku.dk> <26502@hydra.gatech.EDU> Sender: news@athena.mit.edu (News system) Reply-To: scs@adam.mit.edu Followup-To: comp.os.msdos.programmer Organization: Thermal Technologies, Cambridge, MA Lines: 89 In article <26502@hydra.gatech.EDU> jt2@prism.gatech.EDU (TROSTEL,JOHN M) writes: >>cn@allgfx.agi.oz (Con Neri) writes: >>>We have been getting an error >>>with a particular piece of code, namely >>> scanf: floating point formats not linked. >>> Abnormal Program termination. >>> Can some one shed some light on what this means? >i have found the same problem. The way I worked around it was to declare >a new float variable, say fl_var, and use it to read in my data. >Anyone else figure this out more? Anyone from Borland about to tell >us how to fix this? This issue faintly amazes me. I can't believe that: 1. there are still people who have not heard about this problem, 2. Borland apparently still hasn't fixed it, 3. the problem exists in the first place, and 4. so many programs manage to elicit it. (Neither 1 nor 4 are flames; I'm just, as I say, faintly amazed.) There's no need to speculate on this problem. It is explained in both the comp.lang.c and comp.sys.ibm.pc.misc FAQ lists. Here's the whole story (at least, as much of it as I know), for those who care: printf is actually a miniature interpreter, and only discovers at run time which format specifiers appear in its format string. Since the floating-point code for dealing with %e, %f, and %g is substantial, and since many programs do not use floating point, it's tempting to leave the floating-point code out for programs which don't need it, especially on machines with limited address spaces. In fact, Ritchie's original PDP-11 C compiler did so, albeit with considerably more success than does Turbo C. The basic idea is that there are two copies of the conceptual equivalent of printf.obj (printf.o for us Unix fans) lying around: one which handles %e, %f, and %g, and one which doesn't. The compiler communicates with the linker somehow, informing it whether the program is using floating point or not, and whether the full-blown or truncated printf code should be linked. (Note that the algorithm is imperfect: if the program isn't using floating point, %e, %f, and %g can't be needed, but they might not be needed if the program is using floating point, either. However, "program uses floating point" is in principle computable at compile time, while "%e, %f, or %g might get passed to printf" isn't.) How does the compiler determine that a "program uses floating point?" Ritchie's compiler asserts that a program uses floating point if a variable is declared as float or double (or, as I recall, a pointer to same), and if that variable is then used. (Even this heuristic isn't perfect; Doug Gwyn claims to have augmented it to handle a few more, really obscure cases, but I don't know the details -- perhaps they involve casts.) Turbo C apparently asserts that a program uses floating point only if the program actually calls for floating point arithmetic. I don't know why Turbo C uses such an obviously inadequate heuristic, particularly when a simple, correct one exists (and was used by a highly visible, 15 year old compiler). It may be that the printf float/nofloat decision is driven by the (equally broken) PC floating-point-via emulator/coprocessor/both/neither distinction, rather than by a "magic" extra undefined external (which is how Ritchie's compiler did it, with the symbol __fltused). I'm sure that the folks on comp.os.msdos.programmer (where this discussion really belongs, and to where followups have been redirected) could provide more information. (I have heard that recent releases of Turbo C finally manage to correct this problem. I would appreciate any confirmation of this rumor.) The remaining puzzle is why so many programs are bitten by this bug. How many real programs read floating point values in and printf them back out (or printf compile-time floating point constants) without doing any arithmetic on them? (This is not to blame the victim, or to excuse Borland for having the bug. The test programs which are used to demonstrate the bugs are always stripped down, as bug-demonstrating test programs should be. I wonder why the longer programs from which the test programs were stripped down managed not to do enough floating-point arithmetic to trigger proper linking? Perhaps the problem only comes up when people write little test programs to play with printf floating-point specifiers, and there are enough of those little test programs to account for the frequency of the question.) Steve Summit scs@adam.mit.edu