X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Fcommon_allocation.c;h=73758481559863addddce045d49bb2e5758bbbe4;hb=03512957fb04969d08fb7eac0952a747aa9596ae;hp=1828d826a5a24a4355f92b0b6dd528adc6219f83;hpb=3bbb7d09f0f2d5f07a3ad7f90b179ddc6831f9a3;p=oweals%2Fgnunet.git diff --git a/src/util/common_allocation.c b/src/util/common_allocation.c index 1828d826a..737584815 100644 --- a/src/util/common_allocation.c +++ b/src/util/common_allocation.c @@ -1,10 +1,10 @@ /* This file is part of GNUnet. - (C) 2001, 2002, 2003, 2005, 2006 Christian Grothoff (and other contributing authors) + Copyright (C) 2001, 2002, 2003, 2005, 2006 GNUnet e.V. GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2, or (at your + by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but @@ -14,8 +14,8 @@ You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /** @@ -24,7 +24,7 @@ * @author Christian Grothoff */ #include "platform.h" -#include "gnunet_common.h" +#include "gnunet_crypto_lib.h" #if HAVE_MALLOC_H #include #endif @@ -32,9 +32,9 @@ #include #endif -#define LOG(kind,...) GNUNET_log_from (kind, "util",__VA_ARGS__) +#define LOG(kind,...) GNUNET_log_from (kind, "util-common-allocation",__VA_ARGS__) -#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) +#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util-common-allocation", syscall) #ifndef INT_MAX #define INT_MAX 0x7FFFFFFF @@ -53,35 +53,115 @@ static LONG mem_used = 0; * memory is available. * * @param size how many bytes of memory to allocate, do NOT use - * this function (or GNUNET_malloc) to allocate more than several MB + * this function (or GNUNET_malloc()) to allocate more than several MB * of memory, if you are possibly needing a very large chunk use - * GNUNET_xmalloc_unchecked_ instead. - * @param filename where in the code was the call to GNUNET_malloc - * @param linenumber where in the code was the call to GNUNET_malloc + * #GNUNET_xmalloc_unchecked_() instead. + * @param filename where in the code was the call to GNUNET_malloc() + * @param linenumber where in the code was the call to GNUNET_malloc() * @return pointer to size bytes of memory */ void * -GNUNET_xmalloc_ (size_t size, const char *filename, int linenumber) +GNUNET_xmalloc_ (size_t size, + const char *filename, + int linenumber) { void *ret; /* As a security precaution, we generally do not allow very large - * allocations using the default 'GNUNET_malloc' macro */ - GNUNET_assert_at (size <= GNUNET_MAX_MALLOC_CHECKED, filename, linenumber); - ret = GNUNET_xmalloc_unchecked_ (size, filename, linenumber); - if (ret == NULL) + * allocations using the default 'GNUNET_malloc()' macro */ + GNUNET_assert_at (size <= GNUNET_MAX_MALLOC_CHECKED, + filename, + linenumber); + ret = GNUNET_xmalloc_unchecked_ (size, + filename, + linenumber); + if (NULL == ret) { - LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "malloc"); - GNUNET_abort (); + LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, + "malloc"); + GNUNET_assert (0); } return ret; } +/** + * Allocate memory for a two dimensional array in one block + * and set up pointers. Aborts if no more memory is available. + * Don't use GNUNET_xnew_array_2d_ directly. Use the + * #GNUNET_new_array_2d macro. + * The memory of the elements will be zero'ed out. + * + * @param n size of the first dimension + * @param m size of the second dimension + * @param elementSize size of a single element in bytes + * @param filename where is this call being made (for debugging) + * @param linenumber line where this call is being made (for debugging) + * @return allocated memory, never NULL + */ +void ** +GNUNET_xnew_array_2d_ (size_t n, size_t m, size_t elementSize, + const char *filename, int linenumber) +{ + /* use char pointer internally to avoid void pointer arithmetic warnings */ + char **ret = GNUNET_xmalloc_ (n * sizeof (void *) + /* 1. dim header */ + n * m * elementSize, /* element data */ + filename, linenumber); + + for (size_t i = 0; i < n; i++) + ret[i] = (char *)ret + /* base address */ + n * sizeof (void *) + /* skip 1. dim header */ + i * m * elementSize; /* skip to 2. dim row header */ + return (void **)ret; +} + + +/** + * Allocate memory for a three dimensional array in one block + * and set up pointers. Aborts if no more memory is available. + * Don't use GNUNET_xnew_array_3d_ directly. Use the + * #GNUNET_new_array_3d macro. + * The memory of the elements will be zero'ed out. + * + * @param n size of the first dimension + * @param m size of the second dimension + * @param o size of the third dimension + * @param elementSize size of a single element in bytes + * @param filename where is this call being made (for debugging) + * @param linenumber line where this call is being made (for debugging) + * @return allocated memory, never NULL + */ +void *** +GNUNET_xnew_array_3d_ (size_t n, size_t m, size_t o, size_t elementSize, + const char *filename, int linenumber) +{ + /* use char pointer internally to avoid void pointer arithmetic warnings */ + char ***ret = GNUNET_xmalloc_ (n * sizeof (void **) + /* 1. dim header */ + n * m * sizeof (void *) + /* 2. dim header */ + n * m * o * elementSize, /* element data */ + filename, linenumber); + + for (size_t i = 0; i < n; i++) + { + /* need to cast to (char *) temporarily for byte level acuracy */ + ret[i] = (char **)((char *)ret + /* base address */ + n * sizeof (void **) + /* skip 1. dim header */ + i * m * sizeof (void *)); /* skip to 2. dim header */ + for (size_t j = 0; j < m; j++) + ret[i][j] = (char *)ret + /* base address */ + n * sizeof (void **) + /* skip 1. dim header */ + n * m * sizeof (void *) + /* skip 2. dim header */ + i * m * o * elementSize + /* skip to 2. dim part */ + j * o * elementSize; /* skip to 3. dim row data */ + } + return (void ***)ret; +} + + /** * Allocate and initialize memory. Checks the return value, aborts if no more - * memory is available. Don't use GNUNET_xmemdup_ directly. Use the - * GNUNET_memdup macro. + * memory is available. Don't use #GNUNET_xmemdup_() directly. Use the + * GNUNET_memdup() macro. * * @param buf buffer to initialize from (must contain size bytes) * @param size number of bytes to allocate @@ -90,7 +170,9 @@ GNUNET_xmalloc_ (size_t size, const char *filename, int linenumber) * @return allocated memory, never NULL */ void * -GNUNET_xmemdup_ (const void *buf, size_t size, const char *filename, +GNUNET_xmemdup_ (const void *buf, + size_t size, + const char *filename, int linenumber) { void *ret; @@ -108,30 +190,31 @@ GNUNET_xmemdup_ (const void *buf, size_t size, const char *filename, if (ret == NULL) { LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "malloc"); - GNUNET_abort (); + GNUNET_assert (0); } #ifdef W32_MEM_LIMIT *((size_t *) ret) = size; ret = &((size_t *) ret)[1]; mem_used += size; #endif - memcpy (ret, buf, size); + GNUNET_memcpy (ret, buf, size); return ret; } - /** - * Wrapper around malloc. Allocates size bytes of memory. + * Wrapper around malloc(). Allocates size bytes of memory. * The memory will be zero'ed out. * * @param size the number of bytes to allocate - * @param filename where in the code was the call to GNUNET_malloc_large - * @param linenumber where in the code was the call to GNUNET_malloc_large + * @param filename where in the code was the call to GNUNET_malloc_unchecked() + * @param linenumber where in the code was the call to GNUNET_malloc_unchecked() * @return pointer to size bytes of memory, NULL if we do not have enough memory */ void * -GNUNET_xmalloc_unchecked_ (size_t size, const char *filename, int linenumber) +GNUNET_xmalloc_unchecked_ (size_t size, + const char *filename, + int linenumber) { void *result; @@ -142,7 +225,7 @@ GNUNET_xmalloc_unchecked_ (size_t size, const char *filename, int linenumber) #endif result = malloc (size); - if (result == NULL) + if (NULL == result) return NULL; memset (result, 0, size); @@ -159,15 +242,19 @@ GNUNET_xmalloc_unchecked_ (size_t size, const char *filename, int linenumber) /** * Reallocate memory. Checks the return value, aborts if no more * memory is available. + * The content of the intersection of the new and old size will be unchanged. * * @param ptr the pointer to reallocate * @param n how many bytes of memory to allocate - * @param filename where in the code was the call to GNUNET_realloc - * @param linenumber where in the code was the call to GNUNET_realloc + * @param filename where in the code was the call to GNUNET_realloc() + * @param linenumber where in the code was the call to GNUNET_realloc() * @return pointer to size bytes of memory */ void * -GNUNET_xrealloc_ (void *ptr, size_t n, const char *filename, int linenumber) +GNUNET_xrealloc_ (void *ptr, + size_t n, + const char *filename, + int linenumber) { #ifdef W32_MEM_LIMIT n += sizeof (size_t); @@ -178,7 +265,7 @@ GNUNET_xrealloc_ (void *ptr, size_t n, const char *filename, int linenumber) if ((NULL == ptr) && (n > 0)) { LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "realloc"); - GNUNET_abort (); + GNUNET_assert (0); } #ifdef W32_MEM_LIMIT ptr = &((size_t *) ptr)[1]; @@ -197,6 +284,9 @@ GNUNET_xrealloc_ (void *ptr, size_t n, const char *filename, int linenumber) #if WINDOWS #define M_SIZE(p) _msize (p) #endif +#if HAVE_MALLOC_NP_H +#include +#endif #if HAVE_MALLOC_USABLE_SIZE #define M_SIZE(p) malloc_usable_size (p) #elif HAVE_MALLOC_SIZE @@ -208,13 +298,17 @@ GNUNET_xrealloc_ (void *ptr, size_t n, const char *filename, int linenumber) * want to keep track of allocations. * * @param ptr the pointer to free - * @param filename where in the code was the call to GNUNET_array_grow - * @param linenumber where in the code was the call to GNUNET_array_grow + * @param filename where in the code was the call to GNUNET_free + * @param linenumber where in the code was the call to GNUNET_free */ void -GNUNET_xfree_ (void *ptr, const char *filename, int linenumber) +GNUNET_xfree_ (void *ptr, + const char *filename, + int linenumber) { - GNUNET_assert_at (ptr != NULL, filename, linenumber); + GNUNET_assert_at (NULL != ptr, + filename, + linenumber); #ifdef W32_MEM_LIMIT ptr = &((size_t *) ptr)[-1]; mem_used -= *((size_t *) ptr); @@ -224,57 +318,92 @@ GNUNET_xfree_ (void *ptr, const char *filename, int linenumber) { const uint64_t baadfood = GNUNET_ntohll (0xBAADF00DBAADF00DLL); uint64_t *base = ptr; - size_t s = M_SIZE (ptr); + size_t s = M_SIZE (ptr); size_t i; - + for (i=0;i newCount, filename, linenumber); size = newCount * elementSize; - if (size == 0) + if (0 == size) { tmp = NULL; } else { tmp = GNUNET_xmalloc_ (size, filename, linenumber); - memset (tmp, 0, size); /* client code should not rely on this, though... */ - if (*oldCount > newCount) - *oldCount = newCount; /* shrink is also allowed! */ - memcpy (tmp, *old, elementSize * (*oldCount)); + if (NULL != *old) + { + GNUNET_memcpy (tmp, *old, elementSize * GNUNET_MIN(*oldCount, newCount)); + } } - if (*old != NULL) + if (NULL != *old) { GNUNET_xfree_ (*old, filename, linenumber); } @@ -324,15 +457,17 @@ GNUNET_xgrow_ (void **old, size_t elementSize, unsigned int *oldCount, /** - * Like asprintf, just portable. + * Like asprintf(), just portable. * * @param buf set to a buffer of sufficient size (allocated, caller must free) - * @param format format string (see printf, fprintf, etc.) + * @param format format string (see printf(), fprintf(), etc.) * @param ... data for format string - * @return number of bytes in "*buf" excluding 0-termination + * @return number of bytes in `*@a buf`, excluding 0-termination */ int -GNUNET_asprintf (char **buf, const char *format, ...) +GNUNET_asprintf (char **buf, + const char *format, + ...) { int ret; va_list args; @@ -349,7 +484,7 @@ GNUNET_asprintf (char **buf, const char *format, ...) /** - * Like snprintf, just aborts if the buffer is of insufficient size. + * Like snprintf(), just aborts if the buffer is of insufficient size. * * @param buf pointer to buffer that is written to * @param size number of bytes in buf @@ -358,7 +493,9 @@ GNUNET_asprintf (char **buf, const char *format, ...) * @return number of bytes written to buf or negative value on error */ int -GNUNET_snprintf (char *buf, size_t size, const char *format, ...) +GNUNET_snprintf (char *buf, + size_t size, + const char *format, ...) { int ret; va_list args; @@ -366,7 +503,7 @@ GNUNET_snprintf (char *buf, size_t size, const char *format, ...) va_start (args, format); ret = VSNPRINTF (buf, size, format, args); va_end (args); - GNUNET_assert (ret <= size); + GNUNET_assert (ret < size); return ret; } @@ -386,7 +523,7 @@ GNUNET_copy_message (const struct GNUNET_MessageHeader *msg) msize = ntohs (msg->size); GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader)); ret = GNUNET_malloc (msize); - memcpy (ret, msg, msize); + GNUNET_memcpy (ret, msg, msize); return ret; }