Hi,
The first warning is: widget.h:18:103: Released storage x->name reachable from parameter at return point for, /*@null@*/ extern inline char *widgetName(/*@null@*/ widget *x) { return (x != NULL) ? x->name : NULL; } What you need here is an /*@observer@*/ annotation to indicate that the caller should not modify the result (even though it is a mutable object). This will override the implicit only on the function result. This leaves 2 warnings in widgetNew: widget.c:9:49: Only storage str not released before return widget.c:6:22: Storage str becomes only widget.c:13:32: Fresh storage str not released before return widget.c:10:5: Fresh storage str allocated The first results from the /*@only@*/ annotation on the local variable declaration. This isn't necessary --- splint should be able to figure out there is no memory leak anyway, but it doesn't (there should probably be a warning for memory annotations on local declarations, since local declarations are permitted to change state, it doesn't really make sense to annotate them). The warning for line 13 is a legitimate memory leak --- we should free str before returning. The warnings for widgetInit are similar: widget.c:26:52: Only storage str not released before return Since str is declared with /*@only@*/ in widget.h, the implementation of widgetInit is responsible for its storage. We should free it before returning. Similarly, for x for the next return. After these changes, splint doesn't produce any warnings. The modified code is below. Best, --- Dave widget *widgetNew(const size_t size) { 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) { free (str); 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; if (str != NULL) free (str); return NULL; } if (str == NULL) { errno = EINVAL; widgetFree (x); return NULL; } x->name = (char *) str; if (initialize != 0) *x->name = '\0'; x->flags = 0; return x; } On Tue, 23 Jul 2002 [EMAIL PROTECTED] wrote: > 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 > >