Static checking of C programs with LCLint

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • aarklon@gmail.com

    Static checking of C programs with LCLint

    Hi all,


    see:-

  • Richard Heathfield

    #2
    Re: Static checking of C programs with LCLint

    aarklon@gmail.c om said:
    From that page: "Here is a small C program:

    main()
    {
    int a[10];
    if (sizeof(a)/sizeof(a[0]) -1)
    printf("hello\n ");
    }

    We expected this to print hello, but it did not."

    You might have expected that, but I didn't. I expected it to exhibit
    undefined behaviour.

    "gcc did not give us any hint."

    Really?

    foo.c:2: warning: return-type defaults to `int'
    foo.c:2: warning: function declaration isn't a prototype
    foo.c: In function `main':
    foo.c:4: warning: comparison between signed and unsigned
    foo.c:5: warning: implicit declaration of function `printf'
    foo.c:6: warning: control reaches end of non-void function

    That looks like quite a few hints to me.

    --
    Richard Heathfield <http://www.cpax.org.uk >
    Email: -http://www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999

    Comment

    • user923005

      #3
      Re: Static checking of C programs with LCLint

      On Apr 14, 8:04 am, Richard Heathfield <r...@see.sig.i nvalidwrote:
      aark...@gmail.c om said:
      >
      Hi all,
      >>
      From that page: "Here is a small C program:
      >
      main()
      {
              int a[10];
              if (sizeof(a)/sizeof(a[0]) -1)
                  printf("hello\n ");
      >
      }
      >
       We expected this to print hello, but it did not."
      >
      You might have expected that, but I didn't. I expected it to exhibit
      undefined behaviour.
      >
      "gcc did not give us any hint."
      >
      Really?
      >
      foo.c:2: warning: return-type defaults to `int'
      foo.c:2: warning: function declaration isn't a prototype
      foo.c: In function `main':
      foo.c:4: warning: comparison between signed and unsigned
      foo.c:5: warning: implicit declaration of function `printf'
      foo.c:6: warning: control reaches end of non-void function
      >
      That looks like quite a few hints to me.
      Then again, the article is 7 years old and it was even before the name
      change from LCLint to SPLint.
      I guess it would have been GCC 2.95 or so back then.

      Comment

      • Richard Heathfield

        #4
        Re: Static checking of C programs with LCLint

        user923005 said:
        On Apr 14, 8:04 am, Richard Heathfield <r...@see.sig.i nvalidwrote:
        >aark...@gmail. com said:
        >>
        Hi all,
        >>>>
        >From that page: "Here is a small C program:
        >>
        >main()
        >{
        >int a[10];
        >if (sizeof(a)/sizeof(a[0]) -1)
        >printf("hello\ n");
        >>
        >}
        >>
        >We expected this to print hello, but it did not."
        >>
        >You might have expected that, but I didn't. I expected it to exhibit
        >undefined behaviour.
        >>
        >"gcc did not give us any hint."
        >>
        >Really?
        >>
        >foo.c:2: warning: return-type defaults to `int'
        >foo.c:2: warning: function declaration isn't a prototype
        >foo.c: In function `main':
        >foo.c:4: warning: comparison between signed and unsigned
        >foo.c:5: warning: implicit declaration of function `printf'
        >foo.c:6: warning: control reaches end of non-void function
        >>
        >That looks like quite a few hints to me.
        >
        Then again, the article is 7 years old and it was even before the name
        change from LCLint to SPLint.
        I guess it would have been GCC 2.95 or so back then.
        The above diagnostics were produced by gcc 2.95.3

        --
        Richard Heathfield <http://www.cpax.org.uk >
        Email: -http://www. +rjh@
        Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
        "Usenet is a strange place" - dmr 29 July 1999

        Comment

        • user923005

          #5
          Re: Static checking of C programs with LCLint

          On Apr 14, 12:18 pm, Richard Heathfield <r...@see.sig.i nvalidwrote:
          user923005 said:
          >
          >
          >
          >
          >
          On Apr 14, 8:04 am, Richard Heathfield <r...@see.sig.i nvalidwrote:
          aark...@gmail.c om said:
          >
          Hi all,
          >>
          From that page: "Here is a small C program:
          >
          main()
          {
          int a[10];
          if (sizeof(a)/sizeof(a[0]) -1)
          printf("hello\n ");
          >
          }
          >
          We expected this to print hello, but it did not."
          >
          You might have expected that, but I didn't. I expected it to exhibit
          undefined behaviour.
          >
          "gcc did not give us any hint."
          >
          Really?
          >
          foo.c:2: warning: return-type defaults to `int'
          foo.c:2: warning: function declaration isn't a prototype
          foo.c: In function `main':
          foo.c:4: warning: comparison between signed and unsigned
          foo.c:5: warning: implicit declaration of function `printf'
          foo.c:6: warning: control reaches end of non-void function
          >
          That looks like quite a few hints to me.
          >
          Then again, the article is 7 years old and it was even before the name
          change from LCLint to SPLint.
          I guess it would have been GCC 2.95 or so back then.
          >
          The above diagnostics were produced by gcc 2.95.3
          Here is the code from the article {reformatted a bit}, along with
          compiler and lint diagnostics:

          #include <stdlib.h>
          #include <stdio.h>

          int main00()
          {
          int a[10];
          if (sizeof(a) / sizeof(a[0]) -1)
          printf("hello\n ");
          }


          int main01()
          {
          int a = 0;
          while (a = 1)
          printf("hello\n ");
          return 0;
          }

          int main02()
          {
          int *p = malloc(5 * sizeof(int));
          *p = 1;
          free(p);
          return 0;
          }



          int main03()
          {
          int *p = malloc(5 * sizeof(int));
          if (p == NULL) {
          fprintf(stderr, "error in malloc");
          exit(EXIT_FAILU RE);
          } else
          *p = 1;
          free(p);
          return 0;
          }


          int main04()
          {
          int *p = malloc(5 * sizeof(int));
          int *q;
          q = p;
          free(q);
          free(p);
          return 0;
          }



          #define sqr(p) p * p
          int main05()
          {
          int i = 2,
          j;
          j = sqr(i + 1);
          printf("%d", j); /* prints 5 */
          return 0;
          }


          static void foo0(int *a, int *b)
          { /* @modifies *a@ */
          *a = 1, *b = 2;
          }
          int main06()
          {
          int p = 10,
          q = 20;
          foo0(&p, &q);
          return 0;
          }


          static void foo1(int *a, int *b)
          { /* @modifies nothing@ */
          *a = 1, *b = 2;
          }
          int main07()
          {
          int p = 10,
          q = 20;
          foo1(&p, &q);
          return 0;
          }



          static int abc,
          def;
          static void foo2()
          {

          def = 1;
          }
          int main08()
          {
          int p = 10,
          q = 20;
          foo2(&p, &q);
          return 0;
          }

          int main(void)
          {
          int i;
          i = main00();
          i = main01();
          i = main02();
          i = main03();
          i = main04();
          i = main05();
          i = main06();
          i = main07();
          i = main08();
          return 0;
          }
          /*
          $ gcc -W -Wall -ansi -pedantic foo.c
          foo.c: In function `main00':
          foo.c:7: warning: comparison between signed and unsigned
          foo.c:9: warning: control reaches end of non-void function
          foo.c: In function `main01':
          foo.c:15: warning: suggest parentheses around assignment used as truth
          value
          foo.c: At top level:
          foo.c:93: warning: `abc' defined but not used

          C:\tmp>cl /W4 /Ox foo.c
          Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762
          for 80x86
          Copyright (C) Microsoft Corporation. All rights reserved.

          foo.c
          foo.c(7) : warning C4308: negative integral constant converted to
          unsigned type
          foo.c(7) : warning C4127: conditional expression is constant
          c:\tmp\foo.c(9) : warning C4716: 'main00' : must return a value
          c:\tmp\foo.c(15 ) : warning C4706: assignment within conditional
          expression
          c:\tmp\foo.c(11 2) : warning C4702: unreachable code
          c:\tmp\foo.c(11 7) : warning C4702: unreachable code
          c:\tmp\foo.c(11 8) : warning C4702: unreachable code
          Microsoft (R) Incremental Linker Version 8.00.50727.762
          Copyright (C) Microsoft Corporation. All rights reserved.

          splint:
          foo.c: (in function main00)
          foo.c(7,15): Operands of have incompatible types (arbitrary unsigned
          integral
          type, int): sizeof((a)) / sizeof((a[0])) -1
          To allow arbitrary integral types to match any integral type, use
          +matchanyintegr al.
          foo.c(9,2): Path with no return in function declared to return int
          There is a path through a function declared to return a value on
          which there
          is no return statement. This means the execution may fall through
          without
          returning a meaningful result to the caller. (Use -noret to inhibit
          warning)
          foo.c: (in function main01)
          foo.c(15,12): Test expression for while is assignment expression: a =
          1
          The condition test is an assignment expression. Probably, you mean
          to use ==
          instead of =. If an assignment is intended, add an extra parentheses
          nesting
          (e.g., if ((a = b)) ...) to suppress this message. (Use -predassign
          to
          inhibit warning)
          foo.c(15,12): Test expression for while not boolean, type int: a = 1
          Test expression type is not boolean or int. (Use -predboolint to
          inhibit
          warning)
          foo.c: (in function main02)
          foo.c(23,6): Dereference of possibly null pointer p: *p
          A possibly null pointer is dereferenced. Value is either the result
          of a
          function which may return null (in which case, code should check it
          is not
          null), or a global, parameter or structure field declared with the
          null
          qualifier. (Use -nullderef to inhibit warning)
          foo.c(22,25): Storage p may become null
          foo.c: (in function main04)
          foo.c(49,10): Dead storage p passed as out parameter to free: p
          Memory is used after it has been released (either by passing as an
          only param
          or assigning to an only global). (Use -usereleased to inhibit
          warning)
          foo.c(48,10): Storage p released
          foo.c(93,17): File static variable abc declared but not used
          A variable is declared but never used. Use /*@unused@*/ in front of
          declaration to suppress message. (Use -varuse to inhibit warning)
          foo.c(4,17): Function exported but not used outside foo: main00
          A declaration is exported, but not used outside this module.
          Declaration can
          use static qualifier. (Use -exportlocal to inhibit warning)
          foo.c(9,1): Definition of main00
          foo.c(12,17): Function exported but not used outside foo: main01
          foo.c(18,1): Definition of main01
          foo.c(20,17): Function exported but not used outside foo: main02
          foo.c(26,1): Definition of main02
          foo.c(30,17): Function exported but not used outside foo: main03
          foo.c(40,1): Definition of main03
          foo.c(43,17): Function exported but not used outside foo: main04
          foo.c(51,1): Definition of main04
          foo.c(56,17): Function exported but not used outside foo: main05
          foo.c(63,1): Definition of main05
          foo.c(70,17): Function exported but not used outside foo: main06
          foo.c(76,1): Definition of main06
          foo.c(83,17): Function exported but not used outside foo: main07
          foo.c(89,1): Definition of main07
          foo.c(100,17): Function exported but not used outside foo: main08
          foo.c(106,1): Definition of main08

          PC-Lint:

          --- Module: foo.c (C)
          _
          if (sizeof(a) / sizeof(a[0]) -1)
          foo.c(7) : Warning 574: Signed-unsigned mix with relational
          foo.c(7) : Info 737: Loss of sign in promotion from int to unsigned
          int
          foo.c(7) : Warning 506: Constant value Boolean
          foo.c(7) : Info 774: Boolean within 'if' always evaluates to False
          [Reference:
          file foo.c: line 7]
          foo.c(7) : Info 831: Reference cited in prior message
          _
          }
          foo.c(9) : Warning 533: function 'main00(void)' should return a value
          (see line
          4)
          foo.c(4) : Info 830: Location cited in prior message
          _
          }
          foo.c(9) : Warning 550: Symbol 'a' (line 6) not accessed
          foo.c(6) : Info 830: Location cited in prior message
          _
          }
          foo.c(9) : Note 953: Variable 'a' (line 6) could be declared as const
          --- Eff.
          C++ 3rd Ed. item 3
          foo.c(6) : Info 830: Location cited in prior message
          _
          while (a = 1)
          foo.c(15) : Info 720: Boolean test of assignment
          foo.c(15) : Warning 506: Constant value Boolean
          _
          return 0;
          foo.c(17) : Warning 527: Unreachable code at token 'return'
          _
          }
          foo.c(18) : Warning 550: Symbol 'a' (line 14) not accessed
          foo.c(14) : Info 830: Location cited in prior message
          _
          *p = 1;
          foo.c(23) : Warning 613: Possible use of null pointer 'p' in argument
          to
          operator 'unary *' [Reference: file foo.c: line 22]
          foo.c(22) : Info 831: Reference cited in prior message
          _
          #define sqr(p) p * p
          foo.c(55) : Info 773: Expression-like macro 'sqr' not parenthesized
          _
          j = sqr(i + 1);
          foo.c(60) : Warning 665: Unparenthesized parameter 1 in macro 'sqr' is
          passed
          an expression
          foo.c(60) : Warning 665: Unparenthesized parameter 1 in macro 'sqr' is
          passed
          an expression
          _
          }
          foo.c(63) : Note 953: Variable 'i' (line 58) could be declared as
          const ---
          Eff. C++ 3rd Ed. item 3
          foo.c(58) : Info 830: Location cited in prior message
          _
          foo2(&p, &q);
          foo.c(104) : Error 119: Too many arguments (2) for prototype
          'foo2(void)'
          _
          }
          foo.c(121) : Warning 550: Symbol 'i' (line 110) not accessed
          foo.c(110) : Info 830: Location cited in prior message

          --- Wrap-up for Module: foo.c

          Warning 528: Symbol 'abc' (line 93, file foo.c) not referenced
          foo.c(93) : Info 830: Location cited in prior message
          Warning 551: Symbol 'def' (line 94, file foo.c) not accessed
          foo.c(94) : Info 830: Location cited in prior message

          */

          Comment

          • David Thompson

            #6
            Re: Static checking of C programs with LCLint

            On Mon, 14 Apr 2008 15:04:15 +0000, Richard Heathfield
            <rjh@see.sig.in validwrote:
            >
            From that page: "Here is a small C program:
            >
            main()
            {
            int a[10];
            if (sizeof(a)/sizeof(a[0]) -1)
            printf("hello\n ");
            }
            >
            We expected this to print hello, but it did not."
            >
            You might have expected that, but I didn't. I expected it to exhibit
            undefined behaviour.
            >
            I didn't, unless size_t is narrower than signed int (which is
            permitted, but rarely sensical). Otherwise, the printf call is never
            executed, and has no opportunity to cause UB.

            In C<99 it does produce unspecified exit status, which is bad, but not
            UB. The other style points are also bad style but not UB.

            - formerly david.thompson1 || achar(64) || worldnet.att.ne t

            Comment

            • CBFalconer

              #7
              Re: Static checking of C programs with LCLint

              David Thompson wrote:
              Richard Heathfield <rjh@see.sig.in validwrote:
              >
              .... snip ...
              >
              >From that page: "Here is a small C program:
              >>
              >main() {
              > int a[10];
              > if (sizeof(a)/sizeof(a[0]) -1)
              > printf("hello\n ");
              >}
              >>
              > We expected this to print hello, but it did not."
              >>
              >You might have expected that, but I didn't. I expected it to
              >exhibit undefined behaviour.
              >
              I didn't, unless size_t is narrower than signed int (which is
              permitted, but rarely sensical). Otherwise, the printf call is
              never executed, and has no opportunity to cause UB.
              I didn't, since the quotient of two unsigned values is unsigned,
              and the unsigned equivalent of -1 is always the maximum unsigned
              value, and thus the conditional is never true.

              --
              [mail]: Chuck F (cbfalconer at maineline dot net)
              [page]: <http://cbfalconer.home .att.net>
              Try the download section.

              ** Posted from http://www.teranews.com **

              Comment

              • Eric Sosman

                #8
                Re: Static checking of C programs with LCLint

                CBFalconer wrote:
                [...] the quotient of two unsigned values is unsigned, [...]
                Not if the unsigned values ("types," really) promote
                to int, which is signed. That would be unusual for size_t
                values, as David Thompson pointed out, but is quite common
                with unsigned short, unsigned char, and unsigned bit-fields.

                --
                Eric.Sosman@sun .com

                Comment

                • CBFalconer

                  #9
                  Re: Static checking of C programs with LCLint

                  Eric Sosman wrote:
                  CBFalconer wrote:
                  >
                  >[...] the quotient of two unsigned values is unsigned, [...]
                  >
                  Not if the unsigned values ("types," really) promote
                  to int, which is signed. That would be unusual for size_t
                  values, as David Thompson pointed out, but is quite common
                  with unsigned short, unsigned char, and unsigned bit-fields.
                  True. A useful exception to keep in mind.

                  --
                  [mail]: Chuck F (cbfalconer at maineline dot net)
                  [page]: <http://cbfalconer.home .att.net>
                  Try the download section.


                  ** Posted from http://www.teranews.com **

                  Comment

                  Working...