view src/ploki/xmalloc.c @ 8427:1fc808cd5b1f

<b_jonas> learn can\'t is the most frequent word whose pronunciation varies between /\xc9\x91\xcb\x90/ and /\xc3\xa6/ depending on dialect. The list is: advance after answer ask aunt brass can\'t cast castle chance class command dance demand draft enhance example fast father glass graph grass half last laugh mask master nasty pass past path plant rather sample shan\'t staff task vast
author HackBot
date Thu, 09 Jun 2016 21:28:47 +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);
}