diff --git a/src/include/stdlib.h b/src/include/stdlib.h index 9124a884..bf3a88e0 100644 --- a/src/include/stdlib.h +++ b/src/include/stdlib.h @@ -1,4 +1,4 @@ -/* $OpenBSD: stdlib.h,v 1.39 2006/09/17 16:48:04 djm Exp $ */ +/* $OpenBSD: stdlib.h,v 1.40 2007/09/03 14:37:02 millert Exp $ */ /* $NetBSD: stdlib.h,v 1.25 1995/12/27 21:19:08 jtc Exp $ */ /*- @@ -128,6 +128,7 @@ void *malloc(size_t); void qsort(void *, size_t, size_t, int (*)(const void *, const void *)); int rand(void); void *realloc(void *, size_t); +void *recalloc(void *, size_t, size_t); void srand(unsigned); double strtod(const char *, char **); long strtol(const char *, char **, int); diff --git a/src/lib/libc/stdlib/Makefile.inc b/src/lib/libc/stdlib/Makefile.inc index c7ee0a80..04e84fe9 100644 --- a/src/lib/libc/stdlib/Makefile.inc +++ b/src/lib/libc/stdlib/Makefile.inc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.35 2006/01/13 17:58:09 millert Exp $ +# $OpenBSD: Makefile.inc,v 1.36 2007/09/03 14:37:02 millert Exp $ # stdlib sources .PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/stdlib ${LIBCSRCDIR}/stdlib @@ -55,7 +55,7 @@ MLINKS+=insque.3 remque.3 MLINKS+=labs.3 llabs.3 MLINKS+=lsearch.3 lfind.3 MLINKS+=malloc.3 free.3 malloc.3 realloc.3 malloc.3 calloc.3 -MLINKS+=malloc.3 cfree.3 malloc.3 malloc.conf.5 +MLINKS+=malloc.3 recalloc.3 malloc.3 cfree.3 malloc.3 malloc.conf.5 MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3 MLINKS+=radixsort.3 sradixsort.3 MLINKS+=rand.3 srand.3 rand.3 rand_r.3 diff --git a/src/lib/libc/stdlib/malloc.3 b/src/lib/libc/stdlib/malloc.3 index 35f83a0c..4c5ea84c 100644 --- a/src/lib/libc/stdlib/malloc.3 +++ b/src/lib/libc/stdlib/malloc.3 @@ -30,15 +30,16 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $OpenBSD: malloc.3,v 1.47 2007/08/08 21:24:29 millert Exp $ +.\" $OpenBSD: malloc.3,v 1.48 2007/09/03 14:37:02 millert Exp $ .\" -.Dd $Mdocdate: August 8 2007 $ +.Dd $Mdocdate: September 3 2007 $ .Dt MALLOC 3 .Os .Sh NAME .Nm malloc , .Nm calloc , .Nm realloc , +.Nm recalloc , .Nm free , .Nm cfree .Nd memory allocation and deallocation @@ -50,6 +51,8 @@ .Fn calloc "size_t nmemb" "size_t size" .Ft void * .Fn realloc "void *ptr" "size_t size" +.Ft void * +.Fn recalloc "void *ptr" "size_t nmemb" "size_t size" .Ft void .Fn free "void *ptr" .Ft void @@ -203,7 +206,18 @@ if ((newp = realloc(p, num * size)) == NULL) { ... .Ed .Pp -Malloc will first look for a symbolic link called +The +.Fn recalloc +function is similar to +.Fn realloc +except that it shares semantics with +.Fn calloc +rather than +.Fn malloc . +Newly allocated space is initialized to zero and the resulting size is +checked for integer overflow. +.Pp +These functions will first look for a symbolic link called .Pa /etc/malloc.conf and next check the environment for a variable called .Ev MALLOC_OPTIONS @@ -258,6 +272,8 @@ sizeof(ptr) errors where sizeof(*ptr) is meant. .Dq realloc . Always reallocate when .Fn realloc +or +.Fn recalloc is called, even if the initial allocation was big enough. This can substantially aid in compacting memory. .\".Pp @@ -440,6 +456,12 @@ The .Fn malloc function conforms to .St -ansiC . +.Pp +The +.Fn recalloc +function is an +.Ox +extension. .Sh HISTORY The present implementation of .Fn malloc diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c index 67f5de51..08b8a088 100644 --- a/src/lib/libc/stdlib/malloc.c +++ b/src/lib/libc/stdlib/malloc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: malloc.c,v 1.86 2007/02/12 20:00:14 otto Exp $ */ +/* $OpenBSD: malloc.c,v 1.87 2007/09/03 14:37:02 millert Exp $ */ /* * ---------------------------------------------------------------------------- @@ -250,9 +250,9 @@ static char *malloc_func; /* * Necessary function declarations. */ -static void *imalloc(size_t size); +static void *imalloc(size_t size, int zero_fill); static void ifree(void *ptr); -static void *irealloc(void *ptr, size_t size); +static void *irealloc(void *ptr, size_t size, int zero_fill); static void *malloc_bytes(size_t size); static struct pginfo *pginfo_list; @@ -1188,7 +1188,7 @@ malloc_bytes(size_t size) * Allocate a piece of memory */ static void * -imalloc(size_t size) +imalloc(size_t size, int zero_fill) { void *result; int ptralloc = 0; @@ -1218,7 +1218,7 @@ imalloc(size_t size) if (malloc_abort == 1 && result == NULL) wrterror("allocation failed"); - if (malloc_zero && result != NULL) + if ((malloc_zero || zero_fill) && result != NULL) memset(result, 0, size); if (result && ptralloc) @@ -1230,7 +1230,7 @@ imalloc(size_t size) * Change the size of an allocation. */ static void * -irealloc(void *ptr, size_t size) +irealloc(void *ptr, size_t size, int zero_fill) { void *p; size_t osize; @@ -1253,7 +1253,7 @@ irealloc(void *ptr, size_t size) if (size <= PTR_SIZE) return (ptr); - p = imalloc(size); + p = imalloc(size, zero_fill); if (p) memcpy(p, ptr, PTR_SIZE); ifree(ptr); @@ -1315,7 +1315,9 @@ irealloc(void *ptr, size_t size) if (!malloc_realloc && size <= osize && size > osize - malloc_pagesize) { - if (malloc_junk) + if (zero_fill) + memset((char *)ptr + size, 0, osize - size); + else if (malloc_junk) memset((char *)ptr + size, SOME_JUNK, osize - size); return (ptr); /* ..don't do anything else. */ } @@ -1338,7 +1340,9 @@ irealloc(void *ptr, size_t size) if (!malloc_realloc && size <= osize && (size > osize / 2 || osize == malloc_minsize)) { - if (malloc_junk) + if (zero_fill) + memset((char *) ptr + size, 0, osize - size); + else if (malloc_junk) memset((char *) ptr + size, SOME_JUNK, osize - size); return (ptr); /* ..don't do anything else. */ } @@ -1347,7 +1351,7 @@ irealloc(void *ptr, size_t size) return (NULL); } - p = imalloc(size); + p = imalloc(size, zero_fill); if (p != NULL) { /* copy the lesser of the two sizes, and free the old one */ @@ -1876,7 +1880,7 @@ malloc(size_t size) malloc_recurse(); return (NULL); } - r = imalloc(size); + r = imalloc(size, 0); UTRACE(0, size, r); malloc_active--; _MALLOC_UNLOCK(); @@ -1907,8 +1911,8 @@ free(void *ptr) return; } -void * -realloc(void *ptr, size_t size) +static void * +_realloc(void *ptr, size_t size, int zero_fill) { void *r; @@ -1920,9 +1924,9 @@ realloc(void *ptr, size_t size) } if (ptr == NULL) - r = imalloc(size); + r = imalloc(size, zero_fill); else - r = irealloc(ptr, size); + r = irealloc(ptr, size, zero_fill); UTRACE(ptr, size, r); malloc_active--; @@ -1933,3 +1937,19 @@ realloc(void *ptr, size_t size) } return (r); } + +void * +realloc(void *ptr, size_t size) +{ + return (_realloc(ptr, size, 0)); +} + +void * +recalloc(void *ptr, size_t nmemb, size_t size) +{ + if (nmemb && SIZE_MAX / nmemb < size) { + errno = ENOMEM; + return (NULL); + } + return (_realloc(ptr, nmemb * size, 1)); +}