view src/ploki/xmalloc.c @ 5556:f2e89077ff1d

<oerjan> learn Turkey was the center of an empire that gobbled up much of Eastern Europe and the Middle East, something which brought them into conflict with Ostrich. In the 19th century the overstuffed empire started declining, and after the Great War it was cut up like so much Shish Kebab.
author HackBot
date Fri, 12 Jun 2015 06:39:15 +0000
parents ac0403686959
children
line wrap: on
line source

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