My solution to allocating memory

Discussion in 'C Programming' started by vippstar@gmail.com, Jan 31, 2008.

  1. Guest

    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--;
    }
    , Jan 31, 2008
    #1
    1. Advertising

  2. Guest

    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 --
    , Jan 31, 2008
    #2
    1. Advertising

  3. Guest

    No comments?
    , Jan 31, 2008
    #3
  4. santosh Guest

    wrote:

    > 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.
    santosh, Feb 1, 2008
    #4
  5. pete Guest

    wrote:
    >
    > 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.

    --
    pete
    pete, Feb 1, 2008
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. hall
    Replies:
    4
    Views:
    432
  2. soni29
    Replies:
    6
    Views:
    398
    Kevin Goodsell
    Sep 5, 2003
  3. Axel
    Replies:
    1
    Views:
    721
    stephan beal
    Oct 27, 2003
  4. Sameer
    Replies:
    2
    Views:
    277
    David White
    Nov 3, 2003
  5. Rakesh Kumar
    Replies:
    5
    Views:
    676
    James Kanze
    Dec 21, 2007
Loading...

Share This Page