Pointer to static storage causing warning by code-checker

B

Bas Wassink

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.
 
K

Kenneth Brody

Bas said:
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:[email protected]>
 
B

Bas Wassink

Bas said:
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
 
E

Emmanuel Delahaye

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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top