My solution to allocating memory

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--;
}
 
V

vippstar

Here is an example snippet with this code.

-- snip.c --
#include "xmalloc.c"

void oh_no(void) { fprintf(stderr, "Something went wrong.\n"); }
int main(void) {
size_t n;
void *p;

xmalloc_init();
atexit(oh_no); /* its just an example so i dont check return value
*/

for(n = 0; n < 1024; n++)
(void)xmalloc(1, 0); /* no memory leak, the pointer is held
somewhere */
printf("allocated 1024 xmalloc(1, 0)!\n");
xmalloc_end(); /* free our resources */
xmalloc_init();
p = xmalloc(sizeof "hello world\n", 0);
strcpy(p, "hello world\n");
printf("%s", p);
xfree(p);
return 0;
}
-- snip.c --
 
S

santosh

No comments?

You should have given some time between the previous threads started by
jacob and Malcolm, and yours. Participants are probably too bone weary
at this point to start beating the same carcass once again.
 
P

pete

No comments?

My preference is to have all program termination
statements be located in the definition of main.
xmalloc goes against that philosophy.

The problem that xmalloc is a solution to, is not a real problem.
It's like the problem that all keywords
have more than one character in their spelling,
thus making it impossible to write complicated programs
because you get too tired from all of the extra typing.
The solution to *that* problem has been posted occassionally
by the same poster here for several years. Nobody likes it.

My hard drive makes less noise when I do all
of my freeing and fclosing explicitly before calling exit,
even though I don't have to.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top