Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 8 Jun 2001 16:39:42 -0700 (PDT)
From:      Matt Dillon <dillon@earth.backplane.com>
To:        Peter Pentchev <roam@orbitel.bg>
Cc:        John Baldwin <jhb@FreeBSD.ORG>, hackers@FreeBSD.ORG
Subject:   Re: free() and const warnings
Message-ID:  <200106082339.f58Ndg399460@earth.backplane.com>
References:  <20010607195634.I724@ringworld.oblivion.bg> <XFMail.010607102051.jhb@FreeBSD.org> <20010608114957.C19938@ringworld.oblivion.bg>

next in thread | previous in thread | raw e-mail | index | archive | help

    Here is the whole set of supporting routines.

					-Matt

/*
 * STRDUP.C
 *
 * $Backplane: backplane/src/libsupport/strdup.c,v 1.13 2001/04/03 00:03:18 dillon Exp $
 */

#include "defs.h"

Export char *safe_strdup(const char *s);
Export char *safe_strdup_segment(const char *start, const char *end);
Export char *safe_replace(char **pptr, const char *s);
Export char *safe_replacef(char **pptr, const char *ctl, ...);
Export char *safe_append(char **pptr, const char *s);
Export char *safe_appendf(char **pptr, const char *ctl, ...);

/*
 * safe_strdup() -	Safe version of strdup(), core dump if alloc fails
 */
char *
safe_strdup(const char *s)
{
    char *r;

    if (s == NULL)
	return(NULL);
    if ((r = strdup(s)) == NULL)
	fatalmem();
    return(r);
}

/*
 * safe_replace() -	Free existing string, allocate copy
 *
 *	Allocates a copy of 's' and stores the copy in *pptr.  The
 *	previous contents of *ptr is freed.
 *
 *	Typical useage is to initialize *pptr to NULL, then use
 *	safe_replace() as many times as necessary (or within a loop),
 *	then safe_free(pptr) after all operations are complete.
 *
 *	This code optimizes the case where 's' is the same as *pptr.
 */
char *
safe_replace(char **pptr, const char *s)
{
    /*
     * Same data (also occurs if s == *ptr), nothing to do
     */
    if (*pptr) {
	if (s && strcmp(s, *pptr) == 0)
	    return(*pptr);
	free(*pptr);
    }

    /*
     * free old, dup new.
     */
    *pptr = (s) ? strdup(s) : NULL;
    return(*pptr);
}

/*
 * safe_replacef() -	Free existing string, allocate copy, with formatting
 *
 *	This operates the same as safe_replace(), except a printf-style
 *	format string and arguments is passed rather then a simple string.
 */
char *
safe_replacef(char **pptr, const char *ctl, ...)
{
    va_list va;
    char *optr = *pptr;

    if (ctl) {
	va_start(va, ctl);
	if (vasprintf(pptr, ctl, va) < 0)
	    fatalmem();
	va_end(va);
    }
    safe_free(&optr);
    return(*pptr);
}

/*
 * safe_append() -	Append to an existing string, reallocating as required
 *
 *	*pptr represents allocated storage or NULL.  *pptr is replaced 
 *	with a new string which is the original string with the 's' argument
 *	appended.  The original string is deallocated.
 *
 *	*pptr is usually initialized to NULL, causing this routine to do
 *	the initial allocation as well as the reallocation in successive
 *	calls.  safe_free(pptr) is typically called after all operations
 *	are complete and the result string is no longer needed.
 */
char *
safe_append(char **pptr, const char *s)
{
    char *old;
    char *new;

    if ((old = *pptr) != NULL) {
	int newLen = strlen(old) + strlen(s) + 1;
	new = malloc(newLen);
	snprintf(new, newLen, "%s%s", old, s);
	free(old);
    } else {
	new = strdup(s);
    }
    *pptr = new;
    return(new);
}

/*
 * safe_appendf() -	Var-args version of safe_append()
 *
 *	Operates like safe_append(), but using a printf-like format string
 *	and additional arguments to generate the string to append.
 */
char *
safe_appendf(char **pptr, const char *ctl, ...)
{
    char *old;
    char *new;
    va_list va;

    va_start(va, ctl);
    if ((old = *pptr) != NULL) {
	if (vasprintf(&new, ctl, va) < 0)
	    DBASSERT(0);
	*pptr = new;
	asprintf(&new, "%s%s", old, new);
	free(*pptr);
	free(old);
    } else {
	if (vasprintf(&new, ctl, va) < 0)
	    DBASSERT(0);
    }
    va_end(va);
    *pptr = new;
    return(new);
}

/*
 * safe_strdup_segment() - duplicate a portion of a string
 *
 *	Returns an allocated string representing the specified segment
 *	between start and end (end non-inclusive).  Dumps core if the
 *	allocation fails.  The returned string will be null terminated.
 */
char *
safe_strdup_segment(const char *start, const char *end)
{
    char *new;
    int len;

    if (start == NULL || end == NULL)
	return(NULL);

    if (start > end) {
	const char *temp = end;
	end = start;
	start = temp;
    }

    len = end - start;
    new = safe_malloc(len + 1);
    memcpy(new, start, len);
    new[len] = '\0';
    return(new);
}

/*
 * ASPRINTF.C
 *
 * $Backplane: backplane/src/libsupport/asprintf.c,v 1.4 2001/04/03 00:03:18 dillon Exp $
 */

#include "defs.h"

Export void safe_asprintf(char **pptr, const char *ctl, ...);
Export void safe_vasprintf(char **pptr, const char *ctl, va_list va);

/*
 * safe_asprintf() -	safe version of asprintf()
 *
 *	This routine implements a safe version of asprintf(), which allocates
 *	the result string and stored it in *ptr.  The program will dump
 *	core if the allocation fails.
 *
 *	*ptr need not be initialized to anything in particular prior to
 *	calling this routine.
 *
 *	Since the return value from the stdc asprintf() is not portable, we
 *	simply return void in our safe version.
 */
void 
safe_asprintf(char **pptr, const char *ctl, ...)
{
    va_list va;
    int r;

    va_start(va, ctl);
    r = vasprintf(pptr, ctl, va);
    va_end(va);
    DBASSERT(r >= 0);
}

/*
 * safe_vasprintf() -	safe version of var-args asprintf.
 *
 *	This routine implements a safe version of vasprintf(), which allocates
 *	the result string and stored it in *ptr.  The program will dump
 *	core if the allocation fails.
 *
 *	*ptr need not be initialized to anything in particular prior to
 *	calling this routine.
 *
 *	Since the return value from the stdc vasprintf() is not portable, we
 *	simply return void in our safe version.
 */
void
safe_vasprintf(char **pptr, const char *ctl, va_list va)
{
    int r;

    r = vasprintf(pptr, ctl, va);
    DBASSERT(r >= 0);
}

/*
 * MALLOC.C
 *
 * $Backplane: backplane/src/libsupport/malloc.c,v 1.11 2001/04/03 00:03:18 dillon Exp $
 */

#include "defs.h"

Export void *safe_malloc(size_t bytes);
Export void *safe_realloc(void *ptr, size_t size);
Export void safe_free(char **ptr);

/*
 * safe_malloc() - safe version of malloc.  Dumps core if the allocation fails
 */
void *
safe_malloc(size_t bytes)
{
    char *ptr = malloc(bytes);

    if (ptr == NULL)
	fatalmem();
    return(ptr);
}

/*
 * safe_realloc() - safe version of realloc.  Dumps core if the
 *		    allocation fails
 */
void *
safe_realloc(void *ptr, size_t size)
{
    if (ptr == NULL)
	ptr = malloc(size);
    else
	ptr = realloc(ptr, size);
    if (ptr == NULL)
	fatalmem();
    return(ptr);
}

/*
 * safe_free() - free a string pointer safely.
 *
 *	Given the address of the pointer (rather then the pointer itself),
 *	this routine is a NOP if the pointer is NULL, and will free() and
 *	NULL-out the pointer if it is non-NULL.
 *
 *	This function is typically only used on string pointers.  Structural
 *	allocations should use zalloc() and zfree().
 */

void
safe_free(char **ptr)
{
    if (*ptr) {
	free(*ptr);
	*ptr = NULL;
    }
}


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200106082339.f58Ndg399460>