splint: where is the memory leak?

Discussion in 'C Programming' started by kevin, Jan 8, 2010.

  1. kevin

    kevin Guest

    Hi everyone. I'm scratching my head and can't understand why I'm
    getting a warning from splint on this bit of code:

    1 #include <stdio.h>
    2 #include <ctype.h>
    3
    4 static char *strtolower( char *str )
    5 {
    6 char *s;
    7
    8 for ( s = str; *s; ++s )
    9 *s = tolower( *s );
    10
    11 return str;
    12 }
    13
    14 int main( void )
    15 {
    16 char msg[] = "Hello world";
    17
    18 printf( "%s\n", strtolower( msg ) );
    19 return 0;
    20 }

    $ splint test.c
    Splint 3.1.1 --- 03 Sep 2009

    test.c: (in function strtolower)
    test.c:8:20: Test expression for for not boolean, type char: *s
    Test expression type is not boolean. (Use -predboolothers to inhibit warning)
    test.c:11:12: Implicitly temp storage str returned as implicitly only: str
    Temp storage (associated with a formal parameter) is transferred to a
    non-temporary reference. The storage may be released or new aliases created.
    (Use -temptrans to inhibit warning)
    test.c: (in function main)
    test.c:18:21: New fresh storage (type char *) passed as implicitly temp (not
    released): strtolower(msg)
    A memory leak has been detected. Storage allocated locally is not released
    before the last reference to it is lost. (Use -mustfreefresh to inhibit
    warning)

    Finished checking --- 3 code warnings
    $ gcc -ansi -pedantic -Wall test.c -o test
    $ ./test
    hello world
    $

    Okay, so splint warns me that it has detected a memory leak in the
    printf call, which
    itself calls the function strtolower. I can't see it - I am only
    returning the same address
    that was passed to the function as a parameter. No new memory is being
    allocated, so I
    cannot understand why there would be a memory leak?

    Can any one guide me on why there's a memory leak here? How do I
    correct it or code
    around it?

    Or is splint in error?

    TIA-
    Kevin
     
    kevin, Jan 8, 2010
    #1
    1. Advertising

  2. kevin

    Kaz Kylheku Guest

    On 2010-01-08, kevin <> wrote:
    > Hi everyone. I'm scratching my head and can't understand why I'm
    > getting a warning from splint on this bit of code:


    Splint is a program that, on unadorned C source, produces reams and reams of
    false positives about imaginary situations.

    To use splint properly, you have to write your programs in a special language
    which consists of C, plus splint annotations written C comments.

    The C implementation discards the comments, but they are part of the splint+C
    language.

    Splint is almost totally useless when applied to unannotated C source.

    To learn about this Splint annotation language, you have to---surprise!---read
    the Splint manual.

    > 1 #include <stdio.h>
    > 2 #include <ctype.h>
    > 3
    > 4 static char *strtolower( char *str )


    By the way, don't do this. Identifiers beginning with "str" are reserved
    for use as external names by the C standard, for the library.

    >
    > 5 {
    > 6 char *s;
    > 7
    > 8 for ( s = str; *s; ++s )
    > 9 *s = tolower( *s );
    > 10
    > 11 return str;
    > 12 }
    > 13
    > 14 int main( void )
    > 15 {
    > 16 char msg[] = "Hello world";
    > 17
    > 18 printf( "%s\n", strtolower( msg ) );
    > 19 return 0;
    > 20 }


    So here, by default, this situation looks like a leak:

    printf( "%s\n", strtolower( msg ) );

    The reason is that strtolower(msg) suspiciously looks like a function that
    allocates and returns new storage. In fact, a strtolower function could work by
    leaving the origianl string alone and returning a lower-case version, in which
    case you would have a memory leak.

    splint will not analyze your C code to confirm or refute its suspicion; it
    relies on the annotations. You must somehow tell it that strtolower does not
    allocate new memory.

    Annotations suck, but one useful thing about them is that (like C
    declarations), they allow translation units of the program to be checked
    without access to other translation units.

    Imagine if strtolower was in a third party library, for which you have only a
    header and binary code. How can the static checker decide whether or not
    that printf has a memory leak? Only in two possible ways: analyze the compiled
    binary code, or rely on special annotations added to the header.
     
    Kaz Kylheku, Jan 8, 2010
    #2
    1. Advertising

  3. kevin

    Eric Sosman Guest

    On 1/8/2010 2:31 PM, kevin wrote:
    > Hi everyone. I'm scratching my head and can't understand why I'm getting
    > a warning from splint on this bit of code:
    >
    > 1 #include <stdio.h>
    > 2 #include <ctype.h>
    > 3
    > 4 static char *strtolower( char *str )
    > 5 {
    > 6 char *s;
    > 7
    > 8 for ( s = str; *s; ++s )
    > 9 *s = tolower( *s );
    > 10
    > 11 return str;
    > 12 }
    > 13
    > 14 int main( void )
    > 15 {
    > 16 char msg[] = "Hello world";
    > 17
    > 18 printf( "%s\n", strtolower( msg ) );
    > 19 return 0;
    > 20 }
    >
    > $ splint test.c
    > Splint 3.1.1 --- 03 Sep 2009
    >
    > test.c: (in function strtolower)
    > test.c:8:20: Test expression for for not boolean, type char: *s
    > Test expression type is not boolean. (Use -predboolothers to inhibit
    > warning)


    Translation: "splint is a style tyrant."

    > test.c:11:12: Implicitly temp storage str returned as implicitly only: str
    > Temp storage (associated with a formal parameter) is transferred to a
    > non-temporary reference. The storage may be released or new aliases
    > created.
    > (Use -temptrans to inhibit warning)


    Translation: [beyond my power to translate; I can find no
    meaning and no sense in this message].

    > test.c: (in function main)
    > test.c:18:21: New fresh storage (type char *) passed as implicitly temp
    > (not
    > released): strtolower(msg)
    > A memory leak has been detected. Storage allocated locally is not released
    > before the last reference to it is lost. (Use -mustfreefresh to inhibit
    > warning)


    Translation: "splint is wrong."

    > Finished checking --- 3 code warnings


    Translation: "splint overlooked both the infringement of
    the implementation's name space and the code's only ACTUAL ERROR
    in line 9."

    > Or is splint in error?


    I'm not familiar with splint, but on the evidence presented
    here it deserves to be, er, cast aside.

    --
    Eric Sosman
    lid
     
    Eric Sosman, Jan 8, 2010
    #3
  4. kevin

    Stefan Ram Guest

    Eric Sosman <> writes:
    >> 4 static char *strtolower( char *str )

    > Translation: [beyond my power to translate; I can find no
    >meaning and no sense in this message].


    It might mean that a naïve author might write:

    if( a = malloc( 10 ))
    { strcpy( a, "hi!" );
    b = strtolower( a );
    free( a );
    puts( b ); }

    I.e., it needs to be documented that the result is
    /the same pointer/ as the argument.
     
    Stefan Ram, Jan 8, 2010
    #4
  5. kevin

    Rich Webb Guest

    On Fri, 08 Jan 2010 15:35:31 -0500, Eric Sosman
    <> wrote:

    [snippety snip]
    > I'm not familiar with splint, but on the evidence presented
    >here it deserves to be, er, cast aside.


    An int-arresting pun for a Friday afternoon. Touché, sir!

    --
    Rich Webb Norfolk, VA
     
    Rich Webb, Jan 8, 2010
    #5
  6. kevin

    Ian Collins Guest

    Rich Webb wrote:
    > On Fri, 08 Jan 2010 15:35:31 -0500, Eric Sosman
    > <> wrote:
    >
    > [snippety snip]
    >> I'm not familiar with splint, but on the evidence presented
    >> here it deserves to be, er, cast aside.

    >
    > An int-arresting pun for a Friday afternoon. Touché, sir!


    Or a static Saturday morning!

    --
    Ian Collins
     
    Ian Collins, Jan 8, 2010
    #6
  7. kevin

    kevin Guest

    Thank you everyone for your reply. I'm glad I didn't completely
    misunderstand. I appreciate your comments.

    Kevin
     
    kevin, Jan 9, 2010
    #7
  8. kevin

    katmac Guest

    Kaz Kylheku wrote:
    >
    > Splint is almost totally useless when applied to unannotated C source.
    >


    Yes, but "splint -weak" is actually pretty useful on code without
    annotations.
     
    katmac, Jan 9, 2010
    #8
  9. kevin

    Dann Corbit Guest

    In article <c07b1c45-e536-47cd-8151-751fa081a2f2@
    22g2000yqr.googlegroups.com>, says...
    >
    > Kaz Kylheku wrote:
    > >
    > > Splint is almost totally useless when applied to unannotated C source.
    > >

    >
    > Yes, but "splint -weak" is actually pretty useful on code without
    > annotations.


    Even the default setting is fine if you know when to ignore it.
     
    Dann Corbit, Jan 11, 2010
    #9
  10. kevin

    Richard Bos Guest

    Dann Corbit <> wrote:

    > 22g2000yqr.googlegroups.com>, says...
    > > Kaz Kylheku wrote:
    > > >
    > > > Splint is almost totally useless when applied to unannotated C source.

    > >
    > > Yes, but "splint -weak" is actually pretty useful on code without
    > > annotations.

    >
    > Even the default setting is fine if you know when to ignore it.


    Myeah, but that doesn't say much. Even Dubya's speeches are fine if you
    know when to ignore them. When "when" becomes "always", it is useless.

    Richard
     
    Richard Bos, Jan 13, 2010
    #10
  11. kevin

    Kaz Kylheku Guest

    On 2010-01-13, Richard Bos <> wrote:
    > Dann Corbit <> wrote:
    >
    >> 22g2000yqr.googlegroups.com>, says...
    >> > Kaz Kylheku wrote:
    >> > >
    >> > > Splint is almost totally useless when applied to unannotated C source.
    >> >
    >> > Yes, but "splint -weak" is actually pretty useful on code without
    >> > annotations.

    >>
    >> Even the default setting is fine if you know when to ignore it.

    >
    > Myeah, but that doesn't say much. Even Dubya's speeches are fine if you
    > know when to ignore them. When "when" becomes "always", it is useless.


    The person who might be presumed to be the world's expert in knowing what to
    ignore from splint output (when splint is run on an un-annotated program)
    wasn't happy with the default setting; he encoded his knowledge in the machine,
    in the form of the -weak option.
     
    Kaz Kylheku, Jan 13, 2010
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Greg Roberts

    Using splint on C files under MS VC6

    Greg Roberts, Jan 23, 2004, in forum: C Programming
    Replies:
    0
    Views:
    477
    Greg Roberts
    Jan 23, 2004
  2. Guy Eschemann

    "Implicitly only" splint warnings

    Guy Eschemann, Jan 12, 2005, in forum: C Programming
    Replies:
    2
    Views:
    1,437
    Guy Eschemann
    Jan 13, 2005
  3. Henry Fr?d?ric

    Ignore include header files with Splint

    Henry Fr?d?ric, Mar 23, 2005, in forum: C Programming
    Replies:
    8
    Views:
    1,235
    Tor Rustad
    Mar 29, 2005
  4. Replies:
    1
    Views:
    1,042
    Clever Monkey
    Jul 7, 2006
  5. Peter Bencsik
    Replies:
    2
    Views:
    868
Loading...

Share This Page