On Sun, Apr 27, 2008 at 08:29:33PM +0100, Daniel P. Berrange wrote: > After updating the virBuffer APIs to protect against improper usage I have > been thinking about how we might provider safer memory allocation APIs > with protection against common usage errors and compile time validation of > checks for failure. Here is an updated version which removes the bogus VIR_REALLOC function and illustrates use in capabilities.c which is a more interesting test case than hash.c proxy/Makefile.am | 1 src/capabilities.c | 121 +++++++++++++++++++++++------------------------------ src/hash.c | 113 +++++++++++++++++++++++-------------------------- src/internal.h | 7 ++- src/memory.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/memory.h | 82 +++++++++++++++++++++++++++++++++++ 6 files changed, 313 insertions(+), 128 deletions(-) Dan. Index: src/capabilities.c =================================================================== RCS file: /data/cvs/libvirt/src/capabilities.c,v retrieving revision 1.7 diff -u -p -r1.7 capabilities.c --- src/capabilities.c 28 Apr 2008 15:14:59 -0000 1.7 +++ src/capabilities.c 28 Apr 2008 16:47:48 -0000 @@ -25,6 +25,7 @@ #include "capabilities.h" #include "buf.h" +#include "memory.h" /** @@ -42,7 +43,7 @@ virCapabilitiesNew(const char *arch, { virCapsPtr caps; - if ((caps = calloc(1, sizeof(*caps))) == NULL) + if (VIR_ALLOC(caps) < 0) goto no_memory; if ((caps->host.arch = strdup(arch)) == NULL) @@ -60,53 +61,53 @@ virCapabilitiesNew(const char *arch, static void virCapabilitiesFreeHostNUMACell(virCapsHostNUMACellPtr cell) { - free(cell->cpus); - free(cell); + VIR_FREE(cell->cpus); + VIR_FREE(cell); } static void virCapabilitiesFreeGuestDomain(virCapsGuestDomainPtr dom) { int i; - free(dom->info.emulator); - free(dom->info.loader); + VIR_FREE(dom->info.emulator); + VIR_FREE(dom->info.loader); for (i = 0 ; i < dom->info.nmachines ; i++) - free(dom->info.machines[i]); - free(dom->info.machines); - free(dom->type); + VIR_FREE(dom->info.machines[i]); + VIR_FREE(dom->info.machines); + VIR_FREE(dom->type); - free(dom); + VIR_FREE(dom); } static void virCapabilitiesFreeGuestFeature(virCapsGuestFeaturePtr feature) { - free(feature->name); - free(feature); + VIR_FREE(feature->name); + VIR_FREE(feature); } static void virCapabilitiesFreeGuest(virCapsGuestPtr guest) { int i; - free(guest->ostype); + VIR_FREE(guest->ostype); - free(guest->arch.name); - free(guest->arch.defaultInfo.emulator); - free(guest->arch.defaultInfo.loader); + VIR_FREE(guest->arch.name); + VIR_FREE(guest->arch.defaultInfo.emulator); + VIR_FREE(guest->arch.defaultInfo.loader); for (i = 0 ; i < guest->arch.defaultInfo.nmachines ; i++) - free(guest->arch.defaultInfo.machines[i]); - free(guest->arch.defaultInfo.machines); + VIR_FREE(guest->arch.defaultInfo.machines[i]); + VIR_FREE(guest->arch.defaultInfo.machines); for (i = 0 ; i < guest->arch.ndomains ; i++) virCapabilitiesFreeGuestDomain(guest->arch.domains[i]); - free(guest->arch.domains); + VIR_FREE(guest->arch.domains); for (i = 0 ; i < guest->nfeatures ; i++) virCapabilitiesFreeGuestFeature(guest->features[i]); - free(guest->features); + VIR_FREE(guest->features); - free(guest); + VIR_FREE(guest); } @@ -122,21 +123,21 @@ virCapabilitiesFree(virCapsPtr caps) { for (i = 0 ; i < caps->nguests ; i++) virCapabilitiesFreeGuest(caps->guests[i]); - free(caps->guests); + VIR_FREE(caps->guests); for (i = 0 ; i < caps->host.nfeatures ; i++) - free(caps->host.features[i]); - free(caps->host.features); + VIR_FREE(caps->host.features[i]); + VIR_FREE(caps->host.features); for (i = 0 ; i < caps->host.nnumaCell ; i++) virCapabilitiesFreeHostNUMACell(caps->host.numaCell[i]); - free(caps->host.numaCell); + VIR_FREE(caps->host.numaCell); for (i = 0 ; i < caps->host.nmigrateTrans ; i++) - free(caps->host.migrateTrans[i]); - free(caps->host.migrateTrans); + VIR_FREE(caps->host.migrateTrans[i]); + VIR_FREE(caps->host.migrateTrans); - free(caps->host.arch); - free(caps); + VIR_FREE(caps->host.arch); + VIR_FREE(caps); } @@ -151,12 +152,9 @@ int virCapabilitiesAddHostFeature(virCapsPtr caps, const char *name) { - char **features; - - if ((features = realloc(caps->host.features, - sizeof(*features) * (caps->host.nfeatures+1))) == NULL) + if (VIR_REALLOC_N(caps->host.features, + caps->host.nfeatures + 1) < 0) return -1; - caps->host.features = features; if ((caps->host.features[caps->host.nfeatures] = strdup(name)) == NULL) return -1; @@ -177,12 +175,9 @@ int virCapabilitiesAddHostMigrateTransport(virCapsPtr caps, const char *name) { - char **migrateTrans; - - if ((migrateTrans = realloc(caps->host.migrateTrans, - sizeof(*migrateTrans) * (caps->host.nmigrateTrans+1))) == NULL) + if (VIR_REALLOC_N(caps->host.migrateTrans, + caps->host.nmigrateTrans + 1) < 0) return -1; - caps->host.migrateTrans = migrateTrans; if ((caps->host.migrateTrans[caps->host.nmigrateTrans] = strdup(name)) == NULL) return -1; @@ -208,19 +203,18 @@ virCapabilitiesAddHostNUMACell(virCapsPt int ncpus, const int *cpus) { - virCapsHostNUMACellPtr cell, *cells; + virCapsHostNUMACellPtr cell; - if ((cells = realloc(caps->host.numaCell, - sizeof(*cells) * (caps->host.nnumaCell+1))) == NULL) + if (VIR_REALLOC_N(caps->host.numaCell, + caps->host.nnumaCell + 1) < 0) return -1; - caps->host.numaCell = cells; - if ((cell = calloc(1, sizeof(cell))) == NULL) + if (VIR_ALLOC(cell) < 0) return -1; caps->host.numaCell[caps->host.nnumaCell] = cell; - if ((caps->host.numaCell[caps->host.nnumaCell]->cpus = - malloc(ncpus * sizeof(*cpus))) == NULL) + if (VIR_ALLOC_N(caps->host.numaCell[caps->host.nnumaCell]->cpus, + ncpus) < 0) return -1; memcpy(caps->host.numaCell[caps->host.nnumaCell]->cpus, cpus, @@ -259,10 +253,10 @@ virCapabilitiesAddGuest(virCapsPtr caps, int nmachines, const char *const *machines) { - virCapsGuestPtr guest, *guests; + virCapsGuestPtr guest; int i; - if ((guest = calloc(1, sizeof(*guest))) == NULL) + if (VIR_ALLOC(guest) < 0) goto no_memory; if ((guest->ostype = strdup(ostype)) == NULL) @@ -279,8 +273,8 @@ virCapabilitiesAddGuest(virCapsPtr caps, (guest->arch.defaultInfo.loader = strdup(loader)) == NULL) goto no_memory; if (nmachines) { - if ((guest->arch.defaultInfo.machines = - calloc(nmachines, sizeof(*guest->arch.defaultInfo.machines))) == NULL) + if (VIR_ALLOC_N(guest->arch.defaultInfo.machines, + nmachines) < 0) goto no_memory; for (i = 0 ; i < nmachines ; i++) { if ((guest->arch.defaultInfo.machines[i] = strdup(machines[i])) == NULL) @@ -289,11 +283,9 @@ virCapabilitiesAddGuest(virCapsPtr caps, } } - if ((guests = realloc(caps->guests, - sizeof(*guests) * - (caps->nguests + 1))) == NULL) + if (VIR_REALLOC_N(caps->guests, + caps->nguests + 1) < 0) goto no_memory; - caps->guests = guests; caps->guests[caps->nguests] = guest; caps->nguests++; @@ -325,10 +317,10 @@ virCapabilitiesAddGuestDomain(virCapsGue int nmachines, const char *const *machines) { - virCapsGuestDomainPtr dom, *doms; + virCapsGuestDomainPtr dom; int i; - if ((dom = calloc(1, sizeof(*dom))) == NULL) + if (VIR_ALLOC(dom) < 0) goto no_memory; if ((dom->type = strdup(hvtype)) == NULL) @@ -341,8 +333,7 @@ virCapabilitiesAddGuestDomain(virCapsGue (dom->info.loader = strdup(loader)) == NULL) goto no_memory; if (nmachines) { - if ((dom->info.machines = - calloc(nmachines, sizeof(*dom->info.machines))) == NULL) + if (VIR_ALLOC_N(dom->info.machines, nmachines) < 0) goto no_memory; for (i = 0 ; i < nmachines ; i++) { if ((dom->info.machines[i] = strdup(machines[i])) == NULL) @@ -351,11 +342,9 @@ virCapabilitiesAddGuestDomain(virCapsGue } } - if ((doms = realloc(guest->arch.domains, - sizeof(*doms) * - (guest->arch.ndomains + 1))) == NULL) + if (VIR_REALLOC_N(guest->arch.domains, + guest->arch.ndomains + 1) < 0) goto no_memory; - guest->arch.domains = doms; guest->arch.domains[guest->arch.ndomains] = dom; guest->arch.ndomains++; @@ -383,9 +372,9 @@ virCapabilitiesAddGuestFeature(virCapsGu int defaultOn, int toggle) { - virCapsGuestFeaturePtr feature, *features; + virCapsGuestFeaturePtr feature; - if ((feature = calloc(1, sizeof(*feature))) == NULL) + if (VIR_ALLOC(feature) < 0) goto no_memory; if ((feature->name = strdup(name)) == NULL) @@ -393,11 +382,9 @@ virCapabilitiesAddGuestFeature(virCapsGu feature->defaultOn = defaultOn; feature->toggle = toggle; - if ((features = realloc(guest->features, - sizeof(*features) * - (guest->nfeatures + 1))) == NULL) + if (VIR_REALLOC_N(guest->features, + guest->nfeatures + 1) < 0) goto no_memory; - guest->features = features; guest->features[guest->nfeatures] = feature; guest->nfeatures++; Index: src/hash.c =================================================================== RCS file: /data/cvs/libvirt/src/hash.c,v retrieving revision 1.37 diff -u -p -r1.37 hash.c --- src/hash.c 18 Apr 2008 08:33:23 -0000 1.37 +++ src/hash.c 28 Apr 2008 16:47:48 -0000 @@ -25,6 +25,7 @@ #include <libxml/threads.h> #include "internal.h" #include "hash.h" +#include "memory.h" #define MAX_HASH_LEN 8 @@ -85,22 +86,22 @@ virHashComputeKey(virHashTablePtr table, virHashTablePtr virHashCreate(int size) { - virHashTablePtr table; + virHashTablePtr table = NULL; if (size <= 0) size = 256; - table = malloc(sizeof(*table)); - if (table) { - table->size = size; - table->nbElems = 0; - table->table = calloc(1, size * sizeof(*(table->table))); - if (table->table) { - return (table); - } - free(table); + if (VIR_ALLOC(table) < 0) + return NULL; + + table->size = size; + table->nbElems = 0; + if (VIR_ALLOC_N(table->table, size) < 0) { + VIR_FREE(table); + return NULL; } - return (NULL); + + return table; } /** @@ -136,8 +137,7 @@ virHashGrow(virHashTablePtr table, int s if (oldtable == NULL) return (-1); - table->table = calloc(1, size * sizeof(*(table->table))); - if (table->table == NULL) { + if (VIR_ALLOC_N(table->table, size) < 0) { table->table = oldtable; return (-1); } @@ -170,7 +170,7 @@ virHashGrow(virHashTablePtr table, int s if (table->table[key].valid == 0) { memcpy(&(table->table[key]), iter, sizeof(virHashEntry)); table->table[key].next = NULL; - free(iter); + VIR_FREE(iter); } else { iter->next = table->table[key].next; table->table[key].next = iter; @@ -184,7 +184,7 @@ virHashGrow(virHashTablePtr table, int s } } - free(oldtable); + VIR_FREE(oldtable); #ifdef DEBUG_GROW xmlGenericError(xmlGenericErrorContext, @@ -225,19 +225,19 @@ virHashFree(virHashTablePtr table, virHa next = iter->next; if ((f != NULL) && (iter->payload != NULL)) f(iter->payload, iter->name); - free(iter->name); + VIR_FREE(iter->name); iter->payload = NULL; if (!inside_table) - free(iter); + VIR_FREE(iter); nbElems--; inside_table = 0; iter = next; } inside_table = 0; } - free(table->table); + VIR_FREE(table->table); } - free(table); + VIR_FREE(table); } /** @@ -281,8 +281,7 @@ virHashAddEntry(virHashTablePtr table, c if (insert == NULL) { entry = &(table->table[key]); } else { - entry = malloc(sizeof(*entry)); - if (entry == NULL) + if (VIR_ALLOC(entry) < 0) return (-1); } @@ -354,8 +353,7 @@ virHashUpdateEntry(virHashTablePtr table if (insert == NULL) { entry = &(table->table[key]); } else { - entry = malloc(sizeof(*entry)); - if (entry == NULL) + if (VIR_ALLOC(entry) < 0) return (-1); } @@ -451,10 +449,10 @@ virHashRemoveEntry(virHashTablePtr table if ((f != NULL) && (entry->payload != NULL)) f(entry->payload, entry->name); entry->payload = NULL; - free(entry->name); + VIR_FREE(entry->name); if (prev) { prev->next = entry->next; - free(entry); + VIR_FREE(entry); } else { if (entry->next == NULL) { entry->valid = 0; @@ -462,7 +460,7 @@ virHashRemoveEntry(virHashTablePtr table entry = entry->next; memcpy(&(table->table[key]), entry, sizeof(virHashEntry)); - free(entry); + VIR_FREE(entry); } } table->nbElems--; @@ -535,11 +533,11 @@ int virHashRemoveSet(virHashTablePtr tab if (iter(entry->payload, entry->name, data)) { count++; f(entry->payload, entry->name); - free(entry->name); + VIR_FREE(entry->name); table->nbElems--; if (prev) { prev->next = entry->next; - free(entry); + VIR_FREE(entry); entry = prev; } else { if (entry->next == NULL) { @@ -549,7 +547,7 @@ int virHashRemoveSet(virHashTablePtr tab entry = entry->next; memcpy(&(table->table[i]), entry, sizeof(virHashEntry)); - free(entry); + VIR_FREE(entry); entry = &(table->table[i]); continue; } @@ -689,8 +687,7 @@ virConnectPtr virGetConnect(void) { virConnectPtr ret; - ret = calloc(1, sizeof(*ret)); - if (ret == NULL) { + if (VIR_ALLOC(ret) < 0) { virHashError(NULL, VIR_ERR_NO_MEMORY, _("allocating connection")); goto failed; } @@ -729,7 +726,7 @@ failed: virHashFree(ret->storageVols, (virHashDeallocator) virStorageVolFreeName); pthread_mutex_destroy(&ret->lock); - free(ret); + VIR_FREE(ret); } return(NULL); } @@ -759,11 +756,11 @@ virReleaseConnect(virConnectPtr conn) { if (__lastErr.conn == conn) __lastErr.conn = NULL; - free(conn->name); + VIR_FREE(conn->name); pthread_mutex_unlock(&conn->lock); pthread_mutex_destroy(&conn->lock); - free(conn); + VIR_FREE(conn); } /** @@ -824,8 +821,7 @@ __virGetDomain(virConnectPtr conn, const ret = (virDomainPtr) virHashLookup(conn->domains, name); /* TODO check the UUID */ if (ret == NULL) { - ret = (virDomainPtr) calloc(1, sizeof(*ret)); - if (ret == NULL) { + if (VIR_ALLOC(ret) < 0) { virHashError(conn, VIR_ERR_NO_MEMORY, _("allocating domain")); goto error; } @@ -854,8 +850,8 @@ __virGetDomain(virConnectPtr conn, const error: pthread_mutex_unlock(&conn->lock); if (ret != NULL) { - free(ret->name ); - free(ret); + VIR_FREE(ret->name); + VIR_FREE(ret); } return(NULL); } @@ -888,8 +884,8 @@ virReleaseDomain(virDomainPtr domain) { __lastErr.dom = NULL; domain->magic = -1; domain->id = -1; - free(domain->name); - free(domain); + VIR_FREE(domain->name); + VIR_FREE(domain); DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs); conn->refs--; @@ -962,8 +958,7 @@ __virGetNetwork(virConnectPtr conn, cons ret = (virNetworkPtr) virHashLookup(conn->networks, name); /* TODO check the UUID */ if (ret == NULL) { - ret = (virNetworkPtr) calloc(1, sizeof(*ret)); - if (ret == NULL) { + if (VIR_ALLOC(ret) < 0) { virHashError(conn, VIR_ERR_NO_MEMORY, _("allocating network")); goto error; } @@ -991,8 +986,8 @@ __virGetNetwork(virConnectPtr conn, cons error: pthread_mutex_unlock(&conn->lock); if (ret != NULL) { - free(ret->name ); - free(ret); + VIR_FREE(ret->name); + VIR_FREE(ret); } return(NULL); } @@ -1025,8 +1020,8 @@ virReleaseNetwork(virNetworkPtr network) __lastErr.net = NULL; network->magic = -1; - free(network->name); - free(network); + VIR_FREE(network->name); + VIR_FREE(network); DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs); conn->refs--; @@ -1100,8 +1095,7 @@ __virGetStoragePool(virConnectPtr conn, ret = (virStoragePoolPtr) virHashLookup(conn->storagePools, name); /* TODO check the UUID */ if (ret == NULL) { - ret = (virStoragePoolPtr) calloc(1, sizeof(*ret)); - if (ret == NULL) { + if (VIR_ALLOC(ret) < 0) { virHashError(conn, VIR_ERR_NO_MEMORY, _("allocating storage pool")); goto error; } @@ -1129,8 +1123,8 @@ __virGetStoragePool(virConnectPtr conn, error: pthread_mutex_unlock(&conn->lock); if (ret != NULL) { - free(ret->name); - free(ret); + VIR_FREE(ret->name); + VIR_FREE(ret); } return(NULL); } @@ -1159,8 +1153,8 @@ virReleaseStoragePool(virStoragePoolPtr _("pool missing from connection hash table")); pool->magic = -1; - free(pool->name); - free(pool); + VIR_FREE(pool->name); + VIR_FREE(pool); DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs); conn->refs--; @@ -1232,8 +1226,7 @@ __virGetStorageVol(virConnectPtr conn, c ret = (virStorageVolPtr) virHashLookup(conn->storageVols, key); if (ret == NULL) { - ret = (virStorageVolPtr) calloc(1, sizeof(*ret)); - if (ret == NULL) { + if (VIR_ALLOC(ret) < 0) { virHashError(conn, VIR_ERR_NO_MEMORY, _("allocating storage vol")); goto error; } @@ -1266,9 +1259,9 @@ __virGetStorageVol(virConnectPtr conn, c error: pthread_mutex_unlock(&conn->lock); if (ret != NULL) { - free(ret->name); - free(ret->pool); - free(ret); + VIR_FREE(ret->name); + VIR_FREE(ret->pool); + VIR_FREE(ret); } return(NULL); } @@ -1297,9 +1290,9 @@ virReleaseStorageVol(virStorageVolPtr vo _("vol missing from connection hash table")); vol->magic = -1; - free(vol->name); - free(vol->pool); - free(vol); + VIR_FREE(vol->name); + VIR_FREE(vol->pool); + VIR_FREE(vol); DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs); conn->refs--; Index: src/internal.h =================================================================== RCS file: /data/cvs/libvirt/src/internal.h,v retrieving revision 1.71 diff -u -p -r1.71 internal.h --- src/internal.h 26 Apr 2008 14:22:02 -0000 1.71 +++ src/internal.h 28 Apr 2008 16:47:49 -0000 @@ -78,7 +78,7 @@ extern int debugFlag; #define VIR_DEBUG(category, fmt,...) \ do { if (debugFlag) fprintf (stderr, "DEBUG: %s: %s (" fmt ")\n", category, __func__, __VA_ARGS__); } while (0) #else -#define VIR_DEBUG(category, fmt,...) +#define VIR_DEBUG(category, fmt,...) \ do { } while (0) #endif /* !ENABLE_DEBUG */ @@ -107,9 +107,14 @@ extern int debugFlag; #define ATTRIBUTE_FORMAT(args...) __attribute__((__format__ (args))) #endif +#ifndef ATTRIBUTE_RETURN_CHECK +#define ATTRIBUTE_RETURN_CHECK __attribute__((__warn_unused_result__)) +#endif + #else #define ATTRIBUTE_UNUSED #define ATTRIBUTE_FORMAT(...) +#define ATTRIBUTE_RETURN_CHECK #endif /* __GNUC__ */ /** Index: src/memory.c =================================================================== RCS file: src/memory.c diff -N src/memory.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/memory.c 28 Apr 2008 16:47:49 -0000 @@ -0,0 +1,117 @@ +/* + * memory.c: safer memory allocation + * + * Copyright (C) 2008 Daniel P. Berrange + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <stdlib.h> + +#include "memory.h" + +/** + * virAlloc: + * @ptrptr: pointer to pointer for address of allocated memory + * @size: number of bytes to allocate + * + * Allocate 'size' bytes of memory. Return the address of the + * allocated memory in 'ptrptr'. The newly allocated memory is + * filled with zeros. + * + * Returns -1 on failure to allocate, zero on success + */ +int virAlloc(void *ptrptr, size_t size) +{ + if (size == 0) { + *(void **)ptrptr = NULL; + return 0; + } + + *(void **)ptrptr = calloc(1, size); + if (*(void **)ptrptr == NULL) + return -1; + return 0; +} + +/** + * virAllocN: + * @ptrptr: pointer to pointer for address of allocated memory + * @size: number of bytes to allocate + * @count: number of elements to allocate + * + * Allocate an array of memory 'count' elements long, + * each with 'size' bytes. Return the address of the + * allocated memory in 'ptrptr'. The newly allocated + * memory is filled with zeros. + * + * Returns -1 on failure to allocate, zero on success + */ +int virAllocN(void *ptrptr, size_t size, size_t count) +{ + if (size == 0 || count == 0) { + *(void **)ptrptr = NULL; + return 0; + } + + *(void**)ptrptr = calloc(count, size); + if (*(void**)ptrptr == NULL) + return -1; + return 0; +} + +/** + * virReallocN: + * @ptrptr: pointer to pointer for address of allocated memory + * @size: number of bytes to allocate + * @count: number of elements in array + * + * Resize the block of memory in 'ptrptr' to be an array of + * 'count' elements, each 'size' bytes in length. Update 'ptrptr' + * with the address of the newly allocated memory. On failure, + * 'ptrptr' is not changed and still points to the original memory + * block. The newly allocated memory is filled with zeros. + * + * Returns -1 on failure to allocate, zero on success + */ +int virReallocN(void *ptrptr, size_t size, size_t count) +{ + void *tmp; + if (size == 0 || count == 0) { + free(*(void **)ptrptr); + *(void **)ptrptr = NULL; + return 0; + } + tmp = realloc(*(void**)ptrptr, size * count); + if (!tmp) + return -1; + *(void**)ptrptr = tmp; + return 0; +} + +/** + * virFree: + * @ptrptr: pointer to pointer for address of memory to be freed + * + * Release the chunk of memory in the pointer pointed to by + * the 'ptrptr' variable. After release, 'ptrptr' will be + * updated to point to NULL. + */ +void virFree(void *ptrptr) +{ + free(*(void**)ptrptr); + *(void**)ptrptr = NULL; +} Index: src/memory.h =================================================================== RCS file: src/memory.h diff -N src/memory.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/memory.h 28 Apr 2008 16:47:49 -0000 @@ -0,0 +1,82 @@ +/* + * memory.c: safer memory allocation + * + * Copyright (C) 2008 Daniel P. Berrange + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + + +#ifndef __VIR_MEMORY_H_ +#define __VIR_MEMORY_H_ + +#include "internal.h" + +/* Don't call these directly - use the macros below */ +int virAlloc(void *ptrptr, size_t size) ATTRIBUTE_RETURN_CHECK; +int virAllocN(void *ptrptr, size_t size, size_t count) ATTRIBUTE_RETURN_CHECK; +int virReallocN(void *ptrptr, size_t size, size_t count) ATTRIBUTE_RETURN_CHECK; +void virFree(void *ptrptr); + + +/** + * VIR_ALLOC: + * @ptr: pointer to hold address of allocated memory + * + * Allocate sizeof(*ptr) bytes of memory and store + * the address of allocated memory in 'ptr'. Fill the + * newly allocated memory with zeros. + * + * Returns -1 on failure, 0 on success + */ +#define VIR_ALLOC(ptr) virAlloc(&(ptr), sizeof(*(ptr))) + +/** + * VIR_ALLOC_N: + * @ptr: pointer to hold address of allocated memory + * @count: number of elements to allocate + * + * Allocate an array of 'count' elements, each sizeof(*ptr) + * bytes long and store the address of allocated memory in + * 'ptr'. Fill the newly allocated memory with zeros. + * + * Returns -1 on failure, 0 on success + */ +#define VIR_ALLOC_N(ptr, count) virAllocN(&(ptr), sizeof(*(ptr)), (count)) + +/** + * VIR_REALLOC_N: + * @ptr: pointer to hold address of allocated memory + * @count: number of elements to allocate + * + * Re-allocate an array of 'count' elements, each sizeof(*ptr) + * bytes long and store the address of allocated memory in + * 'ptr'. Fill the newly allocated memory with zeros + * + * Returns -1 on failure, 0 on success + */ +#define VIR_REALLOC_N(ptr, count) virReallocN(&(ptr), sizeof(*(ptr)), (count)) + +/** + * VIR_FREE: + * @ptr: pointer holding address to be freed + * + * Free the memory stored in 'ptr' and update to point + * to NULL. + */ +#define VIR_FREE(ptr) virFree(&(ptr)); + +#endif /* __VIR_MEMORY_H_ */ Index: proxy/Makefile.am =================================================================== RCS file: /data/cvs/libvirt/proxy/Makefile.am,v retrieving revision 1.16 diff -u -p -r1.16 Makefile.am --- proxy/Makefile.am 27 Feb 2008 04:35:08 -0000 1.16 +++ proxy/Makefile.am 28 Apr 2008 16:47:49 -0000 @@ -14,6 +14,7 @@ libvirt_proxy_SOURCES = libvirt_proxy.c @top_srcdir@/src/sexpr.c @top_srcdir@/src/xml.c \ @top_srcdir@/src/xs_internal.c @top_srcdir@/src/buf.c \ @top_srcdir@/src/capabilities.c \ + @top_srcdir@/src/memory.c \ @top_srcdir@/src/util.c \ @top_srcdir@/src/uuid.c libvirt_proxy_LDFLAGS = $(WARN_CFLAGS) -- |: Red Hat, Engineering, Boston -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list