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[i].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[i].Id == k )
return Keywords[i].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