delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1996/09/19/12:17:35

From: "John M. Aldrich" <fighteer AT cs DOT com>
Newsgroups: comp.os.msdos.djgpp
Subject: Re: Lint for DJGPP
Date: Wed, 18 Sep 1996 19:51:14 -0700
Organization: Three pounds of chaos and a pinch of salt
Lines: 169
Message-ID: <3240B522.6CFB@cs.com>
References: <323FFE4B DOT 1CFB AT LSTM DOT Ruhr-UNI-Bochum DOT De>
Reply-To: fighteer AT cs DOT com
NNTP-Posting-Host: ppp211.cs.com
Mime-Version: 1.0
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp

Thomas Demmer wrote:
> 
> Well, Eli said gcc -Wall -pedantic usually suffices,
> here is a little riddle. The following program contains
> 11 bugs/flaws. gcc finds 7. How many do YOU find? ;-)

Aha, a quiz!  Without meaning to start a new thread, I'll
give this one a shot...  (without gcc's help, thank you)

[WARNING:  Do not read further unless you want to see my
 answers to the riddle!  I found anywhere from 11 to 13 (?)
 flaws myself, depending on how purist you want to be.]













/* main prog bsp.c:
 * print square numbers from "lower" to "upper".
 * Range given from commandline
 */
#include <stdio.h>
#include <stdlib.h>
extern int lower, upper;
extern void print_table(int, int);

static const char *PROG;        /* program name */
static void SHOW_USAGE()        /*  how to use */
{
   (void) printf((stderr,"Usage: %s [ [lower ] upper ]\n"),
                   PROG);

*** Holy sh**!  This one almost threw me for a loop, until I realized
*** that in its present form, it will do exactly what it's intended
*** to do.  However, gcc WILL complain that stderr is an unused
*** expression.  (Error #1?)

    exit();

*** #2 - exit() has to be passed a value.  This should always be
*** caught.

}



int main(int argc, char *argv[])   /* MAIN PROGRAM */

*** It has been said that you should, for maximum compatibility,
*** declare argv as:  char **argv
*** I don't know if this is one of the "errors"; but gcc certainly
*** won't catch it AFAIK.

{
    /* Set program name for usage * /
    PROG = argv[0];   /* in SHOW_USAGE */

    if(argc > 3)
       SHOW_USAGE;

*** Error #3 (4?) - You still have to use parens for a function call,
*** no matter what.

    else {
      /*  get upper limit if given */
      if(argc >= 2)
        upper = atoi(argv[argc-1]);

*** Valid, but logically there's no guarantee that the arg in question
*** is an integer.  I don't know if you count this as an error.

      /* get lower if given */
      if (argc == 3);

*** Error #4!  - severe problem here - lose that semicolon!

      lower=atof(argv[1]);

*** Error #5 - lower's an int not a float.  Plus you still can't guarantee
*** that argv[1] will be a number.  This may or may not be flagged except by
*** religiously precise compilers.

      /* print table and exit */
      print_table(lower, upper);

*** Error #6 - Nowhere do I see any initialization for lower and upper.
*** Since they are declared extern, one might be able to assume they
*** are initialized in some theoretical other module, but there's no
*** evidence to suggest it in this case.

      return 0;

*** Error #7 - this return won't be called if that 'else' above isn't
*** executed.  Move it up one level of nesting.  Under -Wall gcc will
*** report that main is declared int but may not return a value.

    }
}

/*
 * PRINTING FUNCTION
 */
#include <stdio.h>

*** Multiple #includes of same file?  Won't cause errors in a properly
*** configured compiler, but BAD all the same.  Error #8


int lower = 1;
int upper = 100;

*** Redeclaration of variables previously declared extern.  Ok, ok -
*** this will work, but it's really evil and nasty.  Plus there's
*** no guarantee (AFAIK) that they will be initialized by the time
*** main() is called.  Tricky... I'd have to flag it for the sake
*** of purity as much as anything (#9).

int print_table(int lo, int hi)

*** Error #10 - print_table above is declared to return void.

{   int i;
     while(lower < upper)
       (void) printf("%7d ",++lower*lower);

*** Logical error - under ANSI there's no way to tell when in this
*** expression lower will be incremented.  Could result in squares
*** every time, but could also result in lower * (lower + 1),
*** depending on implementation (Error #11)

     if ( i % 10  == 0)
        (void) printf("\n");

*** When is i incremented (or initialized for that matter)?  This
*** condition may or may not ever be true.  (#12)

     return i;

*** Error - lo and hi are never used, whilst their global counterparts
*** are.  This causes the globals to be modified instead of the locals,
*** which _can't_ be the programmer's intention.  (#13)
}


> BTW, I found 8.

Well, I seem to have found 13, but two of those (the ones dealing with
declaration/initialization of the globals lower and upper) may not in
fact be errors, no matter how evil and nasty they look in practice.  I
don't have enough experience with truly awful programming to tell.

BTW, you didn't mention in your post if you wanted this in email or on
the newsgroup.  Since this isn't specific to DJGPP, the thread may not
be appreciated if we keep it up for long. :)

-- 
------------------------------------------------------------------------
| John M. Aldrich, aka Fighteer I   |         fighteer AT cs DOT com          |
| Proud owner of what might one day |    http://www.cs.com/fighteer    |
| be a spectacular MUD...           |  Plan: To make Bill Gates suffer |
------------------------------------------------------------------------

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019