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.

Reply via email to