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