From owner-freebsd-hackers Fri Jun 8 16:39:56 2001 Delivered-To: freebsd-hackers@freebsd.org Received: from earth.backplane.com (earth-nat-cw.backplane.com [208.161.114.67]) by hub.freebsd.org (Postfix) with ESMTP id A47EC37B403; Fri, 8 Jun 2001 16:39:44 -0700 (PDT) (envelope-from dillon@earth.backplane.com) Received: (from dillon@localhost) by earth.backplane.com (8.11.3/8.11.2) id f58Ndg399460; Fri, 8 Jun 2001 16:39:42 -0700 (PDT) (envelope-from dillon) Date: Fri, 8 Jun 2001 16:39:42 -0700 (PDT) From: Matt Dillon Message-Id: <200106082339.f58Ndg399460@earth.backplane.com> To: Peter Pentchev Cc: John Baldwin , hackers@FreeBSD.ORG Subject: Re: free() and const warnings References: <20010607195634.I724@ringworld.oblivion.bg> <20010608114957.C19938@ringworld.oblivion.bg> Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG 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