gooddan
Tue, 23 Jul 2002 07:57:49 -0700
Hello all,
First let me say thank you for splint. When I use it, I
feel like I
have an experienced and meticulous C coder looking over
my shoulder.
Lately, I've tried something a little more ambitious, and
either
I don't understand what is wrong with my code or I'm
failing to
annotate it properly, so I'm coming to you for help.
I've made
a small example to show what approach I'm using and what
messages
splint is generating. Essentially I want to malloc
memory for
a structure and a string component of the structure, use
it, and
later free all the memory. Optionally, I want to be able
to use
a non-dynamically allocated structure and string. I'm
including
below the .splintrc file, widget.h, widget.c, and the splint
messages. I'd be very grateful to anyone who can help me
understand
what I need to do here. Thanks. -Dan Good
__.splintrc_________________________________________________
-unrecog
#-mustfreefresh
#-usereleased
-compdef
#-mustfreeonly
#-compmempass
-exportlocal
__widget.h__________________________________________________
#ifndef _WIDGET_H
#define _WIDGET_H 1
#define WIDGET_MALLOCED 1
struct widget {
/*@only@*/ char *name;
unsigned int flags;
};
typedef /*@abstract@*/ struct widget widget;
/*@null@*/ /*@only@*/ widget *widgetNew(const size_t size);
/*@null@*/ widget *widgetInit(/*@null@*/ /*@partial@*/
/*@only@*/ widget *x, /*@null@*/ /*@only@*/ const char
*str, const unsigned int initialize);
void widgetFree(/*@null@*/ /*@only@*/ widget *x);
/*@null@*/ extern inline char *widgetName(/*@null@*/
widget *x) { return (x != NULL) ? x->name : NULL; }
#endif
__widget.c__________________________________________________
#include <stdlib.h>
#include <errno.h>
#include "widget.h"
widget *widgetNew(const size_t size) {
/*@only@*/ char *str;
widget *x;
if (size < 1) { errno = EINVAL; return NULL; }
str = (char *) malloc(size);
if (str == NULL) return NULL; /* malloc sets errno */
x = (widget *) malloc(sizeof(struct widget));
if (x == NULL) return NULL; /* malloc sets errno */
if (widgetInit(x,str,1) == NULL) return NULL;
x->flags |= WIDGET_MALLOCED;
return x;
}
widget *widgetInit(widget *x, const char *str, const
unsigned int initialize) {
if (x == NULL) { errno = EINVAL; return NULL; }
if (str == NULL) { errno = EINVAL; return NULL; }
x->name = (char *) str;
if (initialize != 0) *x->name = '\0';
x->flags = 0;
return x;
}
void widgetFree(widget *x) {
if (x != NULL && (x->flags & WIDGET_MALLOCED) != 0) {
free(x->name);
free(x);
}
}
/*@null@*/ char *widgetName(/*@null@*/ widget *x) {
return (x != NULL) ? x->name : NULL; }
__splint widget.c___________________________________________
Splint 3.0.1.6 --- 19 Jul 2002
widget.h: (in function widgetName)
widget.h:18:103: Released storage x->name reachable from
parameter at return
point
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)
widget.h:18:74: Storage x->name is released
widget.c: (in function widgetNew)
widget.c:9:49: Only storage str not released before return
A memory leak has been detected. Only-qualified storage
is not released
before the last reference to it is lost. (Use
-mustfreeonly to inhibit
warning)
widget.c:6:22: Storage str becomes only
widget.c:13:32: Fresh storage str not released before return
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)
widget.c:10:5: Fresh storage str allocated
widget.c: (in function widgetInit)
widget.c:21:52: Only storage str not released before return
widget.c:20:43: Storage str becomes only
widget.c:22:52: Only storage x not released before return
widget.c:20:28: Storage x becomes only
widget.c: (in function widgetName)
widget.c:36:89: Released storage x->name reachable from
parameter at return
point
widget.c:36:60: Storage x->name is released
Finished checking --- 6 code warnings