Pointer to static storage causing warning by code-checker

Discussion in 'C Programming' started by Bas Wassink, Sep 16, 2005.

  1. Bas Wassink

    Bas Wassink Guest

    Hello there,

    I'm having trouble understanding a warning produced by 'splint', a
    code-checker. The warning produced is:

    keywords.c: (in function keyw_get_string)
    keywords.c:60:31: Released storage Keywords[].Keyword reachable from global
    A global variable does not satisfy its annotations when control
    is transferred. (Use -globstate to inhibit warning)
    keywords.c:60:11: Storage Keywords[].Keyword released

    The line number isn't correct anymore since I snipped some 'irrelevant'
    code. Here's the code that causes the warning:

    /*
    * keywords module for sta65xx, written by Bas Wassink
    * started: 2005-09-13
    * updated: 2005-09-16
    */

    #include <string.h>
    #include <stdio.h>

    #include "globals.h" /* application wide used constants */
    #include "keywords.h" /* prototypes and constants used */

    struct keystruct { /* struct used by Keywords table */
    char *Keyword;
    int Id;
    char *Description;
    };

    /* keywords table */
    static struct keystruct Keywords[] = {
    { "byte", KEYW_BYTE, "data as bytes" },
    { "word", KEYW_WORD, "data as words" },
    { "text", KEYW_TEXT, "data as text" }
    };

    /* return keyword string */
    char *keyw_get_string ( int k )
    {
    int i;

    /* check identifier bounds */
    if ( ( k >= KEYWORDS_AMOUNT ) || ( k < 0 ) )
    return NULL;

    /* look up Id in table */
    for ( i = 0; i < KEYWORDS_AMOUNT; i++ )
    if ( Keywords.Id == k )
    return Keywords.Keyword; /* <= This causes the warning */

    /* Id not found, return NULL as error code (shouldn't happen) */
    return NULL;
    }


    I know I'm returning a pointer to memory accessible only by this module,
    so that's probably what causes the warning, but I still don't quite
    understand the warning.

    If anyone could explain what I might be doing wrong, I'd be much obliged.

    Bas Wassink.
    Bas Wassink, Sep 16, 2005
    #1
    1. Advertising

  2. Bas Wassink wrote:
    >
    > Hello there,
    >
    > I'm having trouble understanding a warning produced by 'splint', a
    > code-checker. The warning produced is:
    >
    > keywords.c: (in function keyw_get_string)
    > keywords.c:60:31: Released storage Keywords[].Keyword reachable from global
    > A global variable does not satisfy its annotations when control
    > is transferred. (Use -globstate to inhibit warning)
    > keywords.c:60:11: Storage Keywords[].Keyword released
    >
    > The line number isn't correct anymore since I snipped some 'irrelevant'
    > code.


    Does the code, as posted, still give the warning?


    > Here's the code that causes the warning:

    [...]
    > /* keywords table */
    > static struct keystruct Keywords[] = {
    > { "byte", KEYW_BYTE, "data as bytes" },
    > { "word", KEYW_WORD, "data as words" },
    > { "text", KEYW_TEXT, "data as text" }
    > };


    Keywords[] is global, and Keywords[].Keyword isn't release anywhere
    ythat I can see, so I don't see why you would get the warning on:

    > /* return keyword string */
    > char *keyw_get_string ( int k )
    > {

    [...]
    > return Keywords.Keyword; /* <= This causes the warning */

    [...]
    > }
    >
    > I know I'm returning a pointer to memory accessible only by this module,
    > so that's probably what causes the warning, but I still don't quite
    > understand the warning.
    >
    > If anyone could explain what I might be doing wrong, I'd be much obliged.


    The memory is accessible to other modules, as long as you pass the
    address somehow to that other module, as you do in the above return
    statement. The Keywords[] array is not known outside the scope of
    this module, due to the "static" modifier, but that doesn't mean you
    can't pass its address around.

    Please verify that the code, as posted, still gives the warning. If
    not, then perhaps part of that "irrelevant" code you snipped wasn't
    so "irrelevant" after all.

    --
    +-------------------------+--------------------+-----------------------------+
    | Kenneth J. Brody | www.hvcomputer.com | |
    | kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
    +-------------------------+--------------------+-----------------------------+
    Don't e-mail me at: <mailto:>
    Kenneth Brody, Sep 16, 2005
    #2
    1. Advertising

  3. Bas Wassink

    Bas Wassink Guest

    On Fri, 16 Sep 2005 11:09:56 -0400, Kenneth Brody wrote:

    > Bas Wassink wrote:
    >>
    >> Hello there,
    >>
    >> I'm having trouble understanding a warning produced by 'splint', a
    >> code-checker. The warning produced is:
    >>
    >> keywords.c: (in function keyw_get_string)
    >> keywords.c:60:31: Released storage Keywords[].Keyword reachable from global
    >> A global variable does not satisfy its annotations when control
    >> is transferred. (Use -globstate to inhibit warning)
    >> keywords.c:60:11: Storage Keywords[].Keyword released
    >>
    >> The line number isn't correct anymore since I snipped some 'irrelevant'
    >> code.

    >
    > Does the code, as posted, still give the warning?
    >
    >
    >> Here's the code that causes the warning:

    > [...]
    >> /* keywords table */
    >> static struct keystruct Keywords[] = {
    >> { "byte", KEYW_BYTE, "data as bytes" },
    >> { "word", KEYW_WORD, "data as words" },
    >> { "text", KEYW_TEXT, "data as text" }
    >> };

    >
    > Keywords[] is global, and Keywords[].Keyword isn't release anywhere
    > ythat I can see, so I don't see why you would get the warning on:
    >
    >> /* return keyword string */
    >> char *keyw_get_string ( int k )
    >> {

    > [...]
    >> return Keywords.Keyword; /* <= This causes the warning */

    > [...]
    >> }
    >>
    >> I know I'm returning a pointer to memory accessible only by this module,
    >> so that's probably what causes the warning, but I still don't quite
    >> understand the warning.
    >>
    >> If anyone could explain what I might be doing wrong, I'd be much obliged.

    >
    > The memory is accessible to other modules, as long as you pass the
    > address somehow to that other module, as you do in the above return
    > statement. The Keywords[] array is not known outside the scope of
    > this module, due to the "static" modifier, but that doesn't mean you
    > can't pass its address around.
    >
    > Please verify that the code, as posted, still gives the warning. If
    > not, then perhaps part of that "irrelevant" code you snipped wasn't
    > so "irrelevant" after all.


    Fair enough, here's the entire piece of code:

    keywords.h:

    /*
    * Header file for keywords.c
    */

    #define KEYWORDS_MAXWIDTH 10
    #define KEYWORDS_AMOUNT 8

    #define KEYW_BYTE 1
    #define KEYW_WORD 2
    #define KEYW_TEXT 3
    #define KEYW_ASC 4
    #define KEYW_PET 5
    #define KEYW_ADDR 6
    #define KEYW_MACRO 7
    #define KEYW_SCOPE 8

    int keyw_get_id ( char *s );
    char *keyw_get_string ( int k );
    void keyw_list ( void );


    keywords.c:

    /*
    * keywords module for sta65xx, written by Bas Wassink
    * started: 2005-09-13
    * updated: 2005-09-16
    */

    #include <string.h>
    #include <stdio.h>

    #include "globals.h" /* application wide used constants */
    #include "keywords.h" /* prototypes and constants used */
    #include "libstr65.h" /* used for safe strlen */

    struct keystruct { /* struct used by Keywords table */
    char *Keyword;
    int Id;
    char *Description;
    };


    /* keywords table */
    static struct keystruct Keywords[] = {
    { "byte", KEYW_BYTE, "data as bytes" },
    { "word", KEYW_WORD, "data as words" },
    { "text", KEYW_TEXT, "data as text" },
    { "asc", KEYW_ASC, "data as ASCII text" },
    { "pet", KEYW_PET, "data as PETSCII text" },
    { "addr", KEYW_ADDR, "set program counter" },
    { "macro", KEYW_MACRO, "declare macro" },
    { "scope", KEYW_SCOPE, "set scope" }
    };

    /* return keyword identifier */
    int keyw_get_id ( char *s )
    {
    int k;

    for ( k = 0; k < KEYWORDS_AMOUNT; k++ ) {
    if ( strcmp ( Keywords[k].Keyword, s ) == 0 )
    return Keywords[k].Id;
    }
    return -1;
    }

    /* return keyword string */
    char *keyw_get_string ( int k )
    {
    int i;

    /* check identifier bounds */
    if ( ( k >= KEYWORDS_AMOUNT ) || ( k < 0 ) )
    return NULL;

    /* look up Id in table */
    for ( i = 0; i < KEYWORDS_AMOUNT; i++ )
    if ( Keywords.Id == k )
    return Keywords.Keyword;

    /* not found, return NULL as error code (shouldn't happen) */
    return NULL;
    }

    /* dump keyword list and descriptions to stdout */
    void keyw_list ( void )
    {
    int k;
    long n;

    for ( k = 0; k < KEYWORDS_AMOUNT; k++ ) {
    fprintf ( stdout, ".%s", Keywords[k].Keyword );
    for ( n = str65_len(Keywords[k].Keyword); n < KEYWORDS_MAXWIDTH; n++ )
    fprintf ( stdout, " " );
    fprintf ( stdout, "%s\n", Keywords[k].Description );
    }
    }


    And here's the output from splint:

    compyx@athlonbox ~/projects/assembler $ splint keywords.c
    Splint 3.1.1 --- 31 Aug 2005

    keywords.c: (in function keyw_get_string)
    keywords.c:52:10: Null storage returned as non-null: NULL
    Function returns a possibly null pointer, but is not declared using
    /*@null@*/ annotation of result. If function may return NULL, add /*@null@*/
    annotation to the return value declaration. (Use -nullret to inhibit warning)
    keywords.c:57:31: Released storage Keywords[].Keyword reachable from global
    A global variable does not satisfy its annotations when control is
    transferred. (Use -globstate to inhibit warning)
    keywords.c:57:11: Storage Keywords[].Keyword released
    keywords.c:60:9: Null storage returned as non-null: NULL

    Finished checking --- 3 code warnings
    Bas Wassink, Sep 16, 2005
    #3
  4. Bas Wassink wrote on 16/09/05 :
    > I'm having trouble understanding a warning produced by 'splint', a
    > code-checker. The warning produced is:
    >
    > keywords.c: (in function keyw_get_string)
    > keywords.c:60:31: Released storage Keywords[].Keyword reachable from global
    > A global variable does not satisfy its annotations when control
    > is transferred. (Use -globstate to inhibit warning)
    > keywords.c:60:11: Storage Keywords[].Keyword released


    Sounds weird...

    > The line number isn't correct anymore since I snipped some 'irrelevant'
    > code. Here's the code that causes the warning:
    >

    <...>

    > I know I'm returning a pointer to memory accessible only by this module,
    > so that's probably what causes the warning, but I still don't quite
    > understand the warning.
    >
    > If anyone could explain what I might be doing wrong, I'd be much obliged.


    I have detected some other minor nitpicks that your code checker have
    ignored... (-ed-)

    /*
    * keywords module for sta65xx, written by Bas Wassink
    * started: 2005-09-13
    * updated: 2005-09-16
    */

    #include <string.h>
    #include <stdio.h>

    /* -ed- my guess (found in missing headers) */
    enum
    {
    KEYW_BYTE,
    KEYW_WORD,
    KEYW_TEXT,
    KEYW_dummy
    };

    /* -ed- 'const' added due to my paranoid settings... */
    char const *keyw_get_string (int k);
    #define KEYWORDS_AMOUNT ((int)(sizeof Keywords/sizeof *Keywords))

    struct keystruct
    { /* struct used by Keywords table */
    /* -ed- 'const' added due to my paranoid settings... */
    char const *Keyword;
    int Id;
    /* -ed- 'const' added due to my paranoid settings... */
    char const *Description;
    };

    /* keywords table */
    static struct keystruct Keywords[] =
    {
    {"byte", KEYW_BYTE, "data as bytes"},
    {"word", KEYW_WORD, "data as words"},
    {"text", KEYW_TEXT, "data as text"}
    };

    /* return keyword string */
    char const *keyw_get_string (int k)
    /* -ed- was 'int' due to my paranoid settings... */
    {
    size_t i; /* -ed- was 'int' due to my paranoid
    settings... */

    /* check identifier bounds */
    if ((k >= KEYWORDS_AMOUNT) || (k < 0))
    return NULL;

    /* look up Id in table */
    for (i = 0; i < KEYWORDS_AMOUNT; i++)
    if (Keywords.Id == k)
    return Keywords.Keyword; /* <= This causes the warning */

    /* Id not found, return NULL as error code (shouldn't happen) */
    return NULL;
    }

    but I don't find anything wrong with the returning of the address of
    the 1st element of a static array.

    --
    Emmanuel
    The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
    The C-library: http://www.dinkumware.com/refxc.html

    "It's specified. But anyone who writes code like that should be
    transmogrified into earthworms and fed to ducks." -- Chris Dollin CLC
    Emmanuel Delahaye, Sep 17, 2005
    #4
    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. Patrick Hoffmann
    Replies:
    3
    Views:
    2,815
    Christian Jan├čen
    Aug 8, 2003
  2. Jim Showalter

    safe to return a pointer to static storage?

    Jim Showalter, Aug 4, 2003, in forum: C Programming
    Replies:
    7
    Views:
    568
    Grant D. Watson
    Aug 6, 2003
  3. sarathy
    Replies:
    2
    Views:
    651
    sarathy
    Jul 17, 2006
  4. Pager O Rama

    MSN BLOCK CHECKER-MSN STATUS CHECKER-MSN PROBLEMS

    Pager O Rama, Apr 4, 2006, in forum: ASP General
    Replies:
    0
    Views:
    225
    Pager O Rama
    Apr 4, 2006
  5. Jacob Grover
    Replies:
    5
    Views:
    304
    Jacob Grover
    Jul 18, 2008
Loading...

Share This Page