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);
+}