Mercurial > repo
diff src/ploki/xmalloc.c @ 4223:ac0403686959
<oerjan> rm -rf src/ploki; mv ploki src
author | HackBot |
---|---|
date | Fri, 20 Dec 2013 22:18:50 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ploki/xmalloc.c Fri Dec 20 22:18:50 2013 +0000 @@ -0,0 +1,168 @@ +#include "config.h" +#include "main.h" +#include "xmalloc.h" + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#ifdef DEBUG_MALLOC + #define IF_DB(x) x +#else + #define IF_DB(x) +#endif + +static struct node { + void *ptr; + struct node *prev, *next; + size_t size; + #if DEBUG_P + const char *file; + unsigned line; + #endif +} *Root; + +#if 0 +int xdump(void) { + struct node *p; + + fprintf(stderr, ":%p\n", Root); + for (p = Root; p; p = p->next) { + fprintf(stderr, "\\<%p [%p]%p %p>\n", p->prev, p, p->ptr, p->next); + assert(p != p->next); + } + fprintf(stderr, "\n"); + return 0; +} +#endif + +void xend(void) { + struct node *p; + + while ((p = Root)) { +#if DEBUG_P + unsigned char *ptr; + for (ptr = p->ptr; memcmp(ptr, &p, sizeof p); ++ptr) + ; + ptr += sizeof p; + fprintf(stderr, "%s: autofreeing pointer %p (%p) from %s:%u\n", Prog, p->ptr, (void *)ptr, p->file, p->line); +#else + fprintf(stderr, "%s: autofreeing pointer %p\n", Prog, p->ptr); +#endif + free(p->ptr); + assert(Root != p->next); + Root = p->next; + free(p); + } +} + +#define XFACTOR(size) ((sizeof (struct node *) - 1) / (size) + 1u) + +#if DEBUG_P +void *(xrealloc)(void *optr, size_t nmemb, const char *file, unsigned line) { +#else +void *xrealloc(void *optr, size_t nmemb) { +#endif + struct node *p; + size_t k; + size_t size; + unsigned char *r; + void *ptr; + + assert(optr != NULL); + + memcpy(&p, (unsigned char *)optr - sizeof Root, sizeof p); + size = p->size; + k = XFACTOR(size) * size; + if (!(ptr = realloc(p->ptr, size * nmemb + k))) { + fprintf(stderr, "%s: realloc(%p, %lu): %s\n", Prog, ptr, (unsigned long)(nmemb * size), strerror(errno)); + abort(); + } + r = (unsigned char *)ptr + k; + #if DEBUG_P + IF_DB(fprintf(stderr, "%s: xrealloc(%zu): %p (%p) from %s:%u -> %p (%p) from %s:%u\n", Prog, nmemb, p->ptr, optr, p->file, p->line, ptr, r, file, line)); + p->file = file; + p->line = line; + #endif + p->ptr = ptr; + return r; +} + +#if DEBUG_P +void *(xmalloc)(size_t nmemb, size_t size, const char *file, unsigned line) { +#else +void *xmalloc(size_t nmemb, size_t size) { +#endif + struct node *p; + size_t k; + unsigned char *r; + + if ((p = malloc(sizeof *p))) { + k = XFACTOR(size) * size; + if (!(p->ptr = malloc(size * nmemb + k))) { + free(p); + goto failure; + } + } else failure: { + fprintf(stderr, "%s: malloc(%lu): %s\n", Prog, (unsigned long)(nmemb * size), strerror(errno)); + abort(); + } + #if DEBUG_P + memset(p->ptr, 'U', k); + #endif + r = (unsigned char *)p->ptr + k; + memcpy(r - sizeof Root, &p, sizeof p); + p->size = size; + p->prev = NULL; + p->next = Root; + #if DEBUG_P + p->file = file; + p->line = line; + IF_DB(fprintf(stderr, "%s: xmalloc(%zu, %zu): %p (%p) from %s:%u\n", Prog, nmemb, size, p->ptr, r, file, line)); + #endif + if (Root) { + Root->prev = p; + } + Root = p; + return r; +} + +#if 0 +#if DEBUG_P +void *(xcalloc)(size_t nmemb, size_t size, const char *file, unsigned line) { + void *const p = xmalloc(nmemb, size, file, line); +#else +void *xcalloc(size_t nmemb, size_t size) { + void *const p = xmalloc(nmemb, size); +#endif + memset(p, '\0', nmemb * size); + return p; +} +#endif + +void xfree(void *ptr) { + struct node *p; + + if (!ptr) + return; + memcpy(&p, (unsigned char *)ptr - sizeof Root, sizeof p); + assert(p != NULL); + DEBUG(memset((unsigned char *)ptr - sizeof Root, 'F', sizeof Root)); + + if (p->next) { + p->next->prev = p->prev; + } + if (p->prev) { + p->prev->next = p->next; + } else { + assert(p == Root); + Root = Root->next; + } + #if DEBUG_P + IF_DB(fprintf(stderr, "%s: xfree(): %p (%p) from %s:%u\n", Prog, p->ptr, ptr, p->file, p->line)); + #endif + free(p->ptr); + free(p); +}