V
vippstar
Recently we had some topics about this (from mr Jacob and mr McLean if
I recall correctly)
I have written a small snippet that works (althought not greatly
optimised), I will explain the functions now.
There are 4 functions
int xmalloc_init(void) /* initializes an xmalloc session, registers
xmalloc_end() with atexit() if it is the first time the function is
called */
void xmalloc_end(void) /* stops an xmalloc session, freeing everything
allocated. can be called even if a session is not started with
xmalloc_init(), and can be called two times in a row (or more) without
crashing */
void * xmalloc(size_t, int) /* first argument is the size to be
allocated, second argument if true, then if xmalloc fails it will
return NULL. if second argument is false, (0) then xmalloc will call
exit(EXIT_FAILURE) */
void xfree(void *) /* frees a pointer allocated with xmalloc().
passing NULL or a pointer that has not been allocated with xmalloc()
does nothing. */
I hope it does not have any bugs.
*** DO NOT MIX xfree() AND free() ***
-- xmalloc.c --
/*
vippstar 2008 - comp.lang.c
please don't credit (nor blame ;-) if you use
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define _xmalloc_chunk_size 128
/* global struct of pointers allocated
all members initialized to 0/NULL because
it is global */
struct {
void ** ptr;
size_t sz; /* pointers initialized */
size_t total; /* total pointers allocated */
} _xmalloc_s;
/* user functions */
int xmalloc_init(void);
void xmalloc_end(void);
void * xmalloc(size_t, int);
void xfree(void *);
/* implementation specific functions */
int xmalloc_resize(void);
void xmalloc_clear(void);
void xmalloc_remove(size_t);
/* debug function */
void xmalloc_debug(void);
void xmalloc_debug(void) {
printf(
"ptr -> %p\n"
"sz -> %zu\n"
"total -> %zu\n\n",
(void *)_xmalloc_s.ptr, _xmalloc_s.sz,
_xmalloc_s.total
);
}
void xmalloc_clear(void) {
_xmalloc_s.ptr = NULL;
_xmalloc_s.sz = 0;
_xmalloc_s.total = 0;
}
int xmalloc_init(void) {
static int first_time = 0;
if(_xmalloc_s.ptr)
return -1; /* xmalloc already initialized */
_xmalloc_s.ptr = malloc(_xmalloc_chunk_size * sizeof
*_xmalloc_s.ptr);
if(_xmalloc_s.ptr == NULL)
return -1;
if(first_time == 0) {
if(atexit(xmalloc_end) == -1) {
free(_xmalloc_s.ptr);
return -1;
}
first_time = 1;
}
_xmalloc_s.total = _xmalloc_chunk_size;
return 0;
}
int xmalloc_resize(void) {
void *tmp;
if(_xmalloc_s.ptr == NULL)
return -1;
tmp = realloc(_xmalloc_s.ptr, (_xmalloc_s.total +
_xmalloc_chunk_size) *
sizeof *_xmalloc_s.ptr);
if(tmp == NULL)
return -1;
_xmalloc_s.ptr = tmp;
_xmalloc_s.total += _xmalloc_chunk_size;
return 0;
}
void xmalloc_end(void) {
size_t n;
for(n = 0; n < _xmalloc_s.sz; n++)
free(_xmalloc_s.ptr[n]);
free(_xmalloc_s.ptr);
xmalloc_clear();
}
/* opt = 0 we exit, opt = 1 we return NULL */
void * xmalloc(size_t size, int opt) {
if(_xmalloc_s.sz == _xmalloc_s.total) {
/* we need to resize */
if(xmalloc_resize() == -1) {
if(opt == 0)
exit(EXIT_FAILURE);
return NULL;
}
}
_xmalloc_s.ptr[_xmalloc_s.sz] = malloc(size);
if(_xmalloc_s.ptr[_xmalloc_s.sz] == NULL) {
if(opt == 0)
exit(EXIT_FAILURE);
return NULL;
}
_xmalloc_s.sz++;
return _xmalloc_s.ptr[_xmalloc_s.sz - 1];
}
void xfree(void * ptr) {
size_t n;
if(ptr != NULL) {
for(n = 0; n < _xmalloc_s.sz; n++)
if(ptr == _xmalloc_s.ptr[n]) {
xmalloc_remove(n);
free(ptr);
}
}
}
void xmalloc_remove(size_t n) {
if(n != _xmalloc_s.sz - 1)
memmove(&_xmalloc_s.ptr[n], &_xmalloc_s.ptr[n+1],
(_xmalloc_s.sz - n - 1) * sizeof *_xmalloc_s.ptr);
_xmalloc_s.sz--;
}
I recall correctly)
I have written a small snippet that works (althought not greatly
optimised), I will explain the functions now.
There are 4 functions
int xmalloc_init(void) /* initializes an xmalloc session, registers
xmalloc_end() with atexit() if it is the first time the function is
called */
void xmalloc_end(void) /* stops an xmalloc session, freeing everything
allocated. can be called even if a session is not started with
xmalloc_init(), and can be called two times in a row (or more) without
crashing */
void * xmalloc(size_t, int) /* first argument is the size to be
allocated, second argument if true, then if xmalloc fails it will
return NULL. if second argument is false, (0) then xmalloc will call
exit(EXIT_FAILURE) */
void xfree(void *) /* frees a pointer allocated with xmalloc().
passing NULL or a pointer that has not been allocated with xmalloc()
does nothing. */
I hope it does not have any bugs.
*** DO NOT MIX xfree() AND free() ***
-- xmalloc.c --
/*
vippstar 2008 - comp.lang.c
please don't credit (nor blame ;-) if you use
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define _xmalloc_chunk_size 128
/* global struct of pointers allocated
all members initialized to 0/NULL because
it is global */
struct {
void ** ptr;
size_t sz; /* pointers initialized */
size_t total; /* total pointers allocated */
} _xmalloc_s;
/* user functions */
int xmalloc_init(void);
void xmalloc_end(void);
void * xmalloc(size_t, int);
void xfree(void *);
/* implementation specific functions */
int xmalloc_resize(void);
void xmalloc_clear(void);
void xmalloc_remove(size_t);
/* debug function */
void xmalloc_debug(void);
void xmalloc_debug(void) {
printf(
"ptr -> %p\n"
"sz -> %zu\n"
"total -> %zu\n\n",
(void *)_xmalloc_s.ptr, _xmalloc_s.sz,
_xmalloc_s.total
);
}
void xmalloc_clear(void) {
_xmalloc_s.ptr = NULL;
_xmalloc_s.sz = 0;
_xmalloc_s.total = 0;
}
int xmalloc_init(void) {
static int first_time = 0;
if(_xmalloc_s.ptr)
return -1; /* xmalloc already initialized */
_xmalloc_s.ptr = malloc(_xmalloc_chunk_size * sizeof
*_xmalloc_s.ptr);
if(_xmalloc_s.ptr == NULL)
return -1;
if(first_time == 0) {
if(atexit(xmalloc_end) == -1) {
free(_xmalloc_s.ptr);
return -1;
}
first_time = 1;
}
_xmalloc_s.total = _xmalloc_chunk_size;
return 0;
}
int xmalloc_resize(void) {
void *tmp;
if(_xmalloc_s.ptr == NULL)
return -1;
tmp = realloc(_xmalloc_s.ptr, (_xmalloc_s.total +
_xmalloc_chunk_size) *
sizeof *_xmalloc_s.ptr);
if(tmp == NULL)
return -1;
_xmalloc_s.ptr = tmp;
_xmalloc_s.total += _xmalloc_chunk_size;
return 0;
}
void xmalloc_end(void) {
size_t n;
for(n = 0; n < _xmalloc_s.sz; n++)
free(_xmalloc_s.ptr[n]);
free(_xmalloc_s.ptr);
xmalloc_clear();
}
/* opt = 0 we exit, opt = 1 we return NULL */
void * xmalloc(size_t size, int opt) {
if(_xmalloc_s.sz == _xmalloc_s.total) {
/* we need to resize */
if(xmalloc_resize() == -1) {
if(opt == 0)
exit(EXIT_FAILURE);
return NULL;
}
}
_xmalloc_s.ptr[_xmalloc_s.sz] = malloc(size);
if(_xmalloc_s.ptr[_xmalloc_s.sz] == NULL) {
if(opt == 0)
exit(EXIT_FAILURE);
return NULL;
}
_xmalloc_s.sz++;
return _xmalloc_s.ptr[_xmalloc_s.sz - 1];
}
void xfree(void * ptr) {
size_t n;
if(ptr != NULL) {
for(n = 0; n < _xmalloc_s.sz; n++)
if(ptr == _xmalloc_s.ptr[n]) {
xmalloc_remove(n);
free(ptr);
}
}
}
void xmalloc_remove(size_t n) {
if(n != _xmalloc_s.sz - 1)
memmove(&_xmalloc_s.ptr[n], &_xmalloc_s.ptr[n+1],
(_xmalloc_s.sz - n - 1) * sizeof *_xmalloc_s.ptr);
_xmalloc_s.sz--;
}