I think you want:
struct freecell_solver_append_string_struct { /*@null@*/ /*@reldef@*/ /*@owned@*/ char *buffer; /*@null@*/ /*@reldef@*/ /*@dependent@*/ char *end_of_buffer; size_t max_size; int size_of_margin; }; This indicates that the buffer field is responsible for the storage it points to, but there may be other references to that storate; the end_of_buffer is a dependent reference (since it points to somewhere in the buffer). The reldef annotations are used to indicate that the fields may not be defined, since freecell_solver_append_string_alloc returns an allocated by not defined structure. --- Dave On Mon, 22 Jul 2002, Shlomi Fish wrote: > > I have the following header: > > /********** app_str.h ***********/ > > #include <string.h> > #include <stdio.h> > #include <stdarg.h> > #include <stdlib.h> > > #ifndef __APP_STR_H > #define __APP_STR_H > > #ifdef __cplusplus > extern "C" { > #endif > > struct freecell_solver_append_string_struct > { > /*@kept@*/ /*@out@*/ char * buffer; > char * end_of_buffer; > size_t max_size; > int size_of_margin; > }; > > typedef struct freecell_solver_append_string_struct > freecell_solver_append_string_t; > > extern /*@null@*/ freecell_solver_append_string_t * > freecell_solver_append_string_alloc(int size_margin); > > extern int freecell_solver_append_string_sprintf( > freecell_solver_append_string_t * app_str, > char * format, > ... > ); > > extern char * freecell_solver_append_string_finalize( > freecell_solver_append_string_t * app_str > ); > > #ifdef __cplusplus > } > #endif > > #endif /* #ifndef __APP_STR_H */ > > /***********************/ > > And the following module: > > > /*************** app_str.c *********************/ > > #include <string.h> > #include <stdio.h> > #include <stdarg.h> > #include <stdlib.h> > > #include "app_str.h" > > #define GROW_BY 4000 > > > freecell_solver_append_string_t * freecell_solver_append_string_alloc(int > size_margin) > { > freecell_solver_append_string_t * app_str; > > if (size_margin > GROW_BY) > { > return NULL; > } > > app_str = malloc(sizeof(freecell_solver_append_string_t)); > if (app_str == NULL) > { > return NULL; > } > > app_str->max_size = GROW_BY; > app_str->end_of_buffer = app_str->buffer = malloc(app_str->max_size); > if (app_str->buffer == NULL) > { > free(app_str); > return NULL; > } > app_str->size_of_margin = size_margin; > > return app_str; > } > > int freecell_solver_append_string_sprintf( > freecell_solver_append_string_t * app_str, > char * format, > ... > ) > { > int num_chars_written; > va_list my_va_list; > > va_start(my_va_list, format); > num_chars_written = vsprintf(app_str->end_of_buffer, format, > my_va_list); > app_str->end_of_buffer += num_chars_written; > /* > * Check to see if we don't have enough space in which case we should > * resize > * */ > if (app_str->buffer + app_str->max_size - app_str->end_of_buffer < > app_str->size_of_margin) > { > char * old_buffer = app_str->buffer; > app_str->max_size += GROW_BY; > app_str->buffer = realloc(app_str->buffer, app_str->max_size); > /* > * Adjust end_of_buffer to the new buffer start > * */ > app_str->end_of_buffer = app_str->buffer + (app_str->end_of_buffer > - old_buffer); > } > > return num_chars_written; > } > > char * freecell_solver_append_string_finalize( > freecell_solver_append_string_t * app_str > ) > { > char * ret; > ret = strdup(app_str->buffer); > free(app_str->buffer); > free(app_str); > return ret; > } > > /*****************************/ > > When I process it with splint (ver. 3.0.1.3.1) I get a gazillion of > warnings. The first ones are: > > <<< > app_str.c: (in function freecell_solver_append_string_alloc) > app_str.c:27:30: Only storage assigned to kept: > app_str->buffer = malloc(app_str->max_size) > The only reference to this storage is transferred to another reference > (e.g., > by returning it) that does not have the only annotation. This may lead > to a > memory leak, since the new reference is not necessarily released. (Use > -onlytrans to inhibit warning) > app_str.c:27:5: Kept storage app_str->buffer assigned to implicitly only: > app_str->end_of_buffer = app_str->buffer = malloc(app_str->max_size) > storage is transferred to a non-temporary reference after being passed > as > keep parameter. The storage may be released or new aliases created. (Use > -kepttrans to inhibit warning) > >>> > > How do I get rid of them? > > Regards, > > Shlomi Fish > > ---------------------------------------------------------------------- > Shlomi Fish [EMAIL PROTECTED] > Home Page: http://t2.technion.ac.il/~shlomif/ > Home E-mail: [EMAIL PROTECTED] > > He who re-invents the wheel, understands much better how a wheel works. >