xmalloc.c - my xmalloc

Discussion in 'C Programming' started by vippstar@gmail.com, Feb 15, 2008.

  1. Guest

    I have posted a previous version of this code some weeks ago which
    unfortunately got no replies.
    I am reposting this and I hope to see comments from c.l.c people.
    You can use this code as you want, credits are not required.
    Hopefully this is portable to any system and doesn't invoke undefined
    behavior anywhere.
    I also don't see how my code would not work with system specific
    concepts such as processes and threads.
    (However, receiving a signal while one of the following functions does
    something will most likely break things)

    This'll be the last time I am posting this (so I won't bother you
    again :)

    Hopefully I'll get some opinions.

    -- xmalloc.c --

    /*
    vippstar 2008 - comp.lang.c
    */
    #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 */

    /* inits an xmalloc session, registers xmalloc_end if
    it's the first time it's called, calling it while
    there is an xmalloc session won't do anything */
    int xmalloc_init(void);

    /* ends an xmalloc session, freeing all resources,
    can be called even if there was no xmalloc_init() before */
    void xmalloc_end(void);

    /* allocates memory like malloc(). if the allocation fails,
    xmalloc looks at the second argument to see what to do
    if the second argument is true, xmalloc will return NULL
    if false, xmalloc will exit(EXIT_FAILURE); */
    void * xmalloc(size_t, int);

    /* frees a pointer previously allocated with xmalloc.
    passing NULL or a pointer not allocated with xmalloc
    won't do anything */
    void xfree(void *);

    /* frees all pointers allocated with xmalloc() in the currect
    xmalloc session */
    void xfreeall(void);

    /* implementation specific functions */
    int xmalloc_resize(void);
    void xmalloc_clear(void);
    void xmalloc_remove(size_t);

    #ifdef DEBUG
    /* 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
    );

    }
    #endif

    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 0; /* 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;

    xfreeall();
    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 xfreeall(void) {

    size_t n;

    for(n = 0; n < _xmalloc_s.sz; n++)
    free(_xmalloc_s.ptr[n]);

    _xmalloc_s.sz = 0;
    }

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

  2. Michael Mair Guest

    wrote:
    > I have posted a previous version of this code some weeks ago which
    > unfortunately got no replies.


    You probably mean
    <>

    Please provide code without tabs; I took the freedom to replace
    every tab by two spaces.

    > I am reposting this and I hope to see comments from c.l.c people.
    > You can use this code as you want, credits are not required.
    > Hopefully this is portable to any system and doesn't invoke undefined
    > behavior anywhere.
    > I also don't see how my code would not work with system specific
    > concepts such as processes and threads.
    > (However, receiving a signal while one of the following functions does
    > something will most likely break things)
    >
    > This'll be the last time I am posting this (so I won't bother you
    > again :)
    >
    > Hopefully I'll get some opinions.
    >
    > -- xmalloc.c --
    >
    > /*
    > vippstar 2008 - comp.lang.c
    > */


    Start with explaining the idea -- either here or at the beginning
    of the header file.
    "Convenience layer for malloc()/free() allowing summary free() from
    about anywhere; registers a cleanup handler via atexit().
    Can handle null pointers returned by malloc() via exit(EXIT_FAILURE)"
    or as flowery as you like it.

    > #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 */


    Comments pointing out the obvious do not improve the code
    quality. If you feel that automagical initialisation of
    static storage duration variables needs explaining, then do
    not rely on the automagic and provide an initialiser.

    > struct {
    > void ** ptr;


    What is ptr good for?

    > size_t sz; /* pointers initialized */


    You probably mean "number of"

    > size_t total; /* total pointers allocated */


    The same.
    What is the relationship between total and sz?
    This is the stuff for comments.
    Note that this is my first impression; I read your code as it is
    and will not "read further code to find out what sz and total are".

    > } _xmalloc_s;


    All file scope identifiers with leading underscore except the
    identifier "_" invade the implementation namespace.
    You already may wander in the shade of the valley of "interesting"
    behaviour.
    Note that giving _xmalloc_s internal linkage does not help this
    problem but at least you are not exposing your housekeeping
    identifiers to the user.

    >
    > /* user functions */


    The following belongs in a header file.

    >
    > /* inits an xmalloc session, registers xmalloc_end if
    > it's the first time it's called, calling it while
    > there is an xmalloc session won't do anything */
    > int xmalloc_init(void);
    >
    > /* ends an xmalloc session, freeing all resources,
    > can be called even if there was no xmalloc_init() before */
    > void xmalloc_end(void);


    How often can I call xmalloc_init()/xmalloc_end()?

    >
    > /* allocates memory like malloc(). if the allocation fails,
    > xmalloc looks at the second argument to see what to do
    > if the second argument is true, xmalloc will return NULL
    > if false, xmalloc will exit(EXIT_FAILURE); */
    > void * xmalloc(size_t, int);
    >
    > /* frees a pointer previously allocated with xmalloc.
    > passing NULL or a pointer not allocated with xmalloc
    > won't do anything */
    > void xfree(void *);
    >
    > /* frees all pointers allocated with xmalloc() in the currect
    > xmalloc session */
    > void xfreeall(void);


    Note that this may be the most dangerous function of them all...
    Suppose you have main() calling xmalloc_init() and xmalloc_end(),
    respectively, and calling a function foo() making use of xmalloc().
    Half a year later, you find that foo() makes a nice utility within
    a larger context and end up with bar():
    void bar (int SomeParam)
    {
    ....
    if (C1) {
    SpecialP = xmalloc(...);
    baz(SomeParam, SpecialP);
    ....
    }
    if (C2) {
    ....
    Something = foo(SomeParam);
    ....
    } else {
    Something = qux();
    }
    if (C1) {
    quux(Something, SpecialP);
    }
    xfree(SpecialP);
    }
    Somehow, your special handling sometimes does not work on
    (C1 && C2) == 1.
    Reason: Some wit (guess who) used xfreeall() in his or her "frame
    function" foo()...

    I'd rather not expose that to the user.

    >
    > /* implementation specific functions */


    "implementation specific" is misleading in comp.lang.c...
    If they are internal functions for use in your xmalloc implementation
    only, then give them internal linkage.

    > int xmalloc_resize(void);


    What does this thing resize? And why does it return int?
    And what does this int mean?

    > void xmalloc_clear(void);
    > void xmalloc_remove(size_t);


    Parameter names are cheap today -- is this parameter an amount,
    an index, just reserved for arbitrary fun? Is it related to
    something in your housekeeping struct?

    >
    > #ifdef DEBUG


    Note: Rather use XMALLOC_DEBUG or similar -- it might be
    double plus unnice if your xmalloc dump came with other debug
    output.

    > /* 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
    > );
    >
    > }


    "z" is not available for C90 and some semi-C99 implementations
    like the gcc on Cygwin just may have to rely on a library that
    does not have it. Casting to unsigned long and using %lu may
    be necessary.

    If you want this to hold up for real use, then provide a
    xmalloc_debug_init()/end() functionality opening a file or
    setting the debug FILE* variable to stdout in your xmalloc_init()/
    end() functions and consider calling xmalloc_debug() on every
    xmalloc()/xfree() operation (via conditional compilation).
    Your typical XMALLOC_DEBUG_PRINT() macro may be even more
    helpful.

    > #endif
    >
    > 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 0; /* 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;


    What do you need that for?
    >
    > xfreeall();
    > 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 xfreeall(void) {
    >
    > size_t n;
    >
    > for(n = 0; n < _xmalloc_s.sz; n++)
    > free(_xmalloc_s.ptr[n]);
    >
    > _xmalloc_s.sz = 0;
    > }
    >
    > void xmalloc_remove(size_t n) {


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


    Note that your internal functions are asymmetric; I would
    have expected xmalloc_insert(size_t Index, void *pNewStorage).
    The xmalloc_resize() function ought to be called xmalloc_expand()
    and there might be need for an xmalloc_compress().

    Your xmalloc_remove() alternatively could just set the respective
    array element to NULL and you could remember, say, up to junk_size
    free()d element numbers and move the memory when necessary.
    This strongly depends on the user's allocation behaviour; in the end,
    you may have to change to a more sophisticated strategy / data
    structures.

    I did not test your code.


    Cheers
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
     
    Michael Mair, Feb 15, 2008
    #2
    1. Advertising

  3. Guest

    On Feb 16, 1:08 am, Michael Mair <> wrote:
    > wrote:
    > > I have posted a previous version of this code some weeks ago which
    > > unfortunately got no replies.

    >
    > You probably mean
    > <>
    >
    > Please provide code without tabs; I took the freedom to replace
    > every tab by two spaces.

    I'll keep that in mind

    >
    >
    > > I am reposting this and I hope to see comments from c.l.c people.
    > > You can use this code as you want, credits are not required.
    > > Hopefully this is portable to any system and doesn't invoke undefined
    > > behavior anywhere.
    > > I also don't see how my code would not work with system specific
    > > concepts such as processes and threads.
    > > (However, receiving a signal while one of the following functions does
    > > something will most likely break things)

    >
    > > This'll be the last time I am posting this (so I won't bother you
    > > again :)

    >
    > > Hopefully I'll get some opinions.

    >
    > > -- xmalloc.c --

    >
    > > /*
    > > vippstar 2008 - comp.lang.c
    > > */

    >
    > Start with explaining the idea -- either here or at the beginning
    > of the header file.
    > "Convenience layer for malloc()/free() allowing summary free() from
    > about anywhere; registers a cleanup handler via atexit().
    > Can handle null pointers returned by malloc() via exit(EXIT_FAILURE)"
    > or as flowery as you like it.
    >
    > > #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 */

    >
    > Comments pointing out the obvious do not improve the code
    > quality. If you feel that automagical initialisation of
    > static storage duration variables needs explaining, then do
    > not rely on the automagic and provide an initialiser.
    >
    > > struct {
    > > void ** ptr;

    >
    > What is ptr good for?
    >
    > > size_t sz; /* pointers initialized */

    >
    > You probably mean "number of"
    >
    > > size_t total; /* total pointers allocated */

    >
    > The same.
    > What is the relationship between total and sz?
    > This is the stuff for comments.
    > Note that this is my first impression; I read your code as it is
    > and will not "read further code to find out what sz and total are".
    >
    > > } _xmalloc_s;

    >
    > All file scope identifiers with leading underscore except the
    > identifier "_" invade the implementation namespace.

    It does? As far as I know only identifiers starting with an underscore
    followed by an uppercase character or another underscore are reserved.
    You are right about the commenting part, as for the names, I'm not
    very good at that. :(

    > > /* user functions */

    >
    > The following belongs in a header file.

    I chose to post it to comp.lang.c as one file to simplify things, but
    yes these declarations should be in a header file.

    >
    >
    > > /* inits an xmalloc session, registers xmalloc_end if
    > > it's the first time it's called, calling it while
    > > there is an xmalloc session won't do anything */
    > > int xmalloc_init(void);

    >
    > > /* ends an xmalloc session, freeing all resources,
    > > can be called even if there was no xmalloc_init() before */
    > > void xmalloc_end(void);

    >
    > How often can I call xmalloc_init()/xmalloc_end()?

    Is that a question or do you mean that someone might wonder that?
    As often as you want.

    >
    >
    > > /* allocates memory like malloc(). if the allocation fails,
    > > xmalloc looks at the second argument to see what to do
    > > if the second argument is true, xmalloc will return NULL
    > > if false, xmalloc will exit(EXIT_FAILURE); */
    > > void * xmalloc(size_t, int);

    >
    > > /* frees a pointer previously allocated with xmalloc.
    > > passing NULL or a pointer not allocated with xmalloc
    > > won't do anything */
    > > void xfree(void *);

    >
    > > /* frees all pointers allocated with xmalloc() in the currect
    > > xmalloc session */
    > > void xfreeall(void);

    >
    > Note that this may be the most dangerous function of them all...
    > Suppose you have main() calling xmalloc_init() and xmalloc_end(),
    > respectively, and calling a function foo() making use of xmalloc().
    > Half a year later, you find that foo() makes a nice utility within
    > a larger context and end up with bar():
    > void bar (int SomeParam)
    > {
    > ....
    > if (C1) {
    > SpecialP = xmalloc(...);
    > baz(SomeParam, SpecialP);
    > ....
    > }
    > if (C2) {
    > ....
    > Something = foo(SomeParam);
    > ....
    > } else {
    > Something = qux();
    > }
    > if (C1) {
    > quux(Something, SpecialP);
    > }
    > xfree(SpecialP);
    > }
    > Somehow, your special handling sometimes does not work on
    > (C1 && C2) == 1.
    > Reason: Some wit (guess who) used xfreeall() in his or her "frame
    > function" foo()...
    >
    > I'd rather not expose that to the user.

    Hm.. true, that would be a very dangerous function.
    Perhaps I should document that it should be used only if followed
    immidiatelly by exit() or _Exit() or a return from main().
    Then again, it could still break if the user has registered a function
    like yours with atexit().

    >
    >
    > > /* implementation specific functions */

    >
    > "implementation specific" is misleading in comp.lang.c...
    > If they are internal functions for use in your xmalloc implementation
    > only, then give them internal linkage.
    >
    > > int xmalloc_resize(void);

    >
    > What does this thing resize? And why does it return int?
    > And what does this int mean?
    >
    > > void xmalloc_clear(void);
    > > void xmalloc_remove(size_t);

    >
    > Parameter names are cheap today -- is this parameter an amount,
    > an index, just reserved for arbitrary fun? Is it related to
    > something in your housekeeping struct?
    >
    >
    >
    > > #ifdef DEBUG

    >
    > Note: Rather use XMALLOC_DEBUG or similar -- it might be
    > double plus unnice if your xmalloc dump came with other debug
    > output.
    >
    > > /* 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
    > > );

    >
    > > }

    >
    > "z" is not available for C90 and some semi-C99 implementations
    > like the gcc on Cygwin just may have to rely on a library that
    > does not have it. Casting to unsigned long and using %lu may
    > be necessary.

    I wrote this with C99 in mind. You are correct, and I will change this
    along with some #ifdef's.
    > If you want this to hold up for real use, then provide a
    > xmalloc_debug_init()/end() functionality opening a file or
    > setting the debug FILE* variable to stdout in your xmalloc_init()/
    > end() functions and consider calling xmalloc_debug() on every
    > xmalloc()/xfree() operation (via conditional compilation).
    > Your typical XMALLOC_DEBUG_PRINT() macro may be even more
    > helpful.


    Thanks, nice ideas.

    > <snipped code>
    >
    > > void xmalloc_end(void) {

    >
    > > size_t n;

    >
    > What do you need that for?

    I don't know, apparently the function does not need it ;-)

    > <snipped code>
    >
    > > void xmalloc_remove(size_t n) {

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

    >
    > Note that your internal functions are asymmetric; I would
    > have expected xmalloc_insert(size_t Index, void *pNewStorage).
    > The xmalloc_resize() function ought to be called xmalloc_expand()
    > and there might be need for an xmalloc_compress().
    >
    > Your xmalloc_remove() alternatively could just set the respective
    > array element to NULL and you could remember, say, up to junk_size
    > free()d element numbers and move the memory when necessary.

    I *do* have problems with object/function naming.
    By the time I posted this I realised that my code lacks xrealloc()/
    xcalloc(), I might add these too.

    > This strongly depends on the user's allocation behaviour; in the end,
    > you may have to change to a more sophisticated strategy / data
    > structures.

    Indeed I have noticed that too, but it was written as a 'quick hack'
    that does some of the stuff discussed in a previous discussion here.
    I don't suggest to a reader to use this code, as there are far more
    sophisticated solutions "out there".
    One could get ideas by looking at the implementation of malloc() and
    friends on his system.

    > I did not test your code.

    Well that is understandable, everyone has his own code to test, but
    still, I was hoping for commenters not testers.
    Thanks again.
     
    , Feb 16, 2008
    #3
  4. Michael Mair Guest

    wrote:
    > On Feb 16, 1:08 am, Michael Mair <> wrote:
    >> wrote:

    <snip>
    >>>struct {

    <snip>
    >>>} _xmalloc_s;

    >>
    >>All file scope identifiers with leading underscore except the
    >>identifier "_" invade the implementation namespace.

    >
    > It does? As far as I know only identifiers starting with an underscore
    > followed by an uppercase character or another underscore are reserved.
    > You are right about the commenting part, as for the names, I'm not
    > very good at that. :(


    The above is not entirely correct. The full version can be found, e.g.,
    in N1124, 7.1.3(Reserved Identifiers), #1:
    ,---
    — All identifiers that begin with an underscore and either an uppercase
    letter or another underscore are always reserved for any use.
    — All identifiers that begin with an underscore are always reserved for
    use as identifiers with file scope in both the ordinary and tag name
    spaces.
    `---
    So, of course, you could use _7xmalloc_s but I would not recommend it...

    >>>/* user functions */

    >>
    >>The following belongs in a header file.

    >
    > I chose to post it to comp.lang.c as one file to simplify things, but
    > yes these declarations should be in a header file.
    >
    >>>/* inits an xmalloc session, registers xmalloc_end if
    >>> it's the first time it's called, calling it while
    >>> there is an xmalloc session won't do anything */
    >>>int xmalloc_init(void);

    >>
    >>>/* ends an xmalloc session, freeing all resources,
    >>> can be called even if there was no xmalloc_init() before */
    >>>void xmalloc_end(void);

    >>
    >>How often can I call xmalloc_init()/xmalloc_end()?

    >
    > Is that a question or do you mean that someone might wonder that?
    > As often as you want.


    The latter; it is "implicitly clear" that this should work as often
    as I want but a sentence stating that explicitly is the thing I
    would look for if reading only the header.
    Calling xmalloc_end() in some "inner function" has the same damage
    potential as xfreeall(). Without an explicit explanation, I do not
    know if I dare calling xmalloc_init() more than once.

    <snip>
    >>>/* frees all pointers allocated with xmalloc() in the currect
    >>> xmalloc session */
    >>>void xfreeall(void);

    >>
    >>Note that this may be the most dangerous function of them all...
    >>Suppose you have main() calling xmalloc_init() and xmalloc_end(),
    >>respectively, and calling a function foo() making use of xmalloc().
    >>Half a year later, you find that foo() makes a nice utility within
    >>a larger context and end up with bar():

    <snip: Example with code drift leading to dangling pointers>
    >>
    >>I'd rather not expose that to the user.

    >
    > Hm.. true, that would be a very dangerous function.
    > Perhaps I should document that it should be used only if followed
    > immidiatelly by exit() or _Exit() or a return from main().
    > Then again, it could still break if the user has registered a function
    > like yours with atexit().


    I would just not give this to the user as it is. Provided with
    a comment explaining why it is dangerous (just as *end() is), it
    may be alright.
    You can suggest that xfreeall() should be called by the same
    function that initializes xmalloc:
    xmalloc_init();
    GetInput();
    TransformToIR();
    TransformToXmlFiles();
    xfreeall(); /* Make room for XSLT */
    PerformXslt();
    Cleanupt();
    xmalloc_end();
    Of course, if you could register xmalloc sessions, then you could
    clean up the unused stuff after each step while preserving the stuff
    needed for later steps. If you think about the problems involved,
    then the simplest possible scheme (just giving xmalloc_init(),
    xmalloc(), and xfree() to the user) seems to be the safest course.

    <snip>

    Cheers
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
     
    Michael Mair, Feb 16, 2008
    #4
  5. Michael Mair <> writes:
    [...]
    > The above is not entirely correct. The full version can be found, e.g.,
    > in N1124, 7.1.3(Reserved Identifiers), #1:

    [...]

    You might want to upgrade to N1256, which incorporates TC3 as well as
    TC1 and TC2.

    http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf

    --
    Keith Thompson (The_Other_Keith) <>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Feb 16, 2008
    #5
  6. Michael Mair Guest

    Keith Thompson wrote:
    > Michael Mair <> writes:
    > [...]
    >
    >>The above is not entirely correct. The full version can be found, e.g.,
    >>in N1124, 7.1.3(Reserved Identifiers), #1:

    >
    > [...]
    >
    > You might want to upgrade to N1256, which incorporates TC3 as well as
    > TC1 and TC2.
    >
    > http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf


    Thank you :)

    Cheers
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
     
    Michael Mair, Feb 16, 2008
    #6
  7. CBFalconer Guest

    wrote:
    > Michael Mair <> wrote:
    >

    .... snip ...
    >>
    >> The following belongs in a header file.

    >
    > I chose to post it to comp.lang.c as one file to simplify things,
    > but yes these declarations should be in a header file.


    I haven't read it, but probably they should not be in a header.
    The only things that go in a header file are the definitions,
    constants, prototypes etc. that you want to export so that other
    programs can access your file. Headers are a misnomer - they are
    not the place to put headings, but they are the place to export
    linkages.

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.



    --
    Posted via a free Usenet account from http://www.teranews.com
     
    CBFalconer, Feb 17, 2008
    #7
  8. CBFalconer Guest

    Michael Mair wrote:
    > Keith Thompson wrote:
    >> Michael Mair <> writes:
    >> [...]
    >>
    >>> The above is not entirely correct. The full version can be found,
    >>> e.g., in N1124, 7.1.3(Reserved Identifiers), #1:

    >>
    >> [...]
    >>
    >> You might want to upgrade to N1256, which incorporates TC3 as well
    >> as TC1 and TC2.
    >>
    >> http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf

    >
    > Thank you :)


    Actually, the whole sequence is:

    N869 Last draft before std issuance
    C99 std The thing itself
    N1124 plus TC1 and TC2
    N1256 plus TC3

    and the last with a decent text version is N869. This is handy for
    searching with grep and text utilities, etc. You can get a version
    adjusted for ease of quoting and searching, bzip2 compressed, at:

    <http://cbfalconer.home.att.net/download/n869_txt.bz2>

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.



    --
    Posted via a free Usenet account from http://www.teranews.com
     
    CBFalconer, Feb 17, 2008
    #8
  9. Guest

    CBFalconer <> wrote:
    >
    > Actually, the whole sequence is:
    >
    > N869 Last draft before std issuance
    > C99 std The thing itself
    > N1124 plus TC1 and TC2
    > N1256 plus TC3


    You left out:

    N949 plus TC1

    -Larry Jones

    That gives me a FABULOUS idea. -- Calvin
     
    , Feb 18, 2008
    #9
  10. Michael Mair Guest

    CBFalconer wrote:
    > wrote:
    >>Michael Mair <> wrote:

    >
    > ... snip ...
    >
    >>>The following belongs in a header file.

    >>
    >>I chose to post it to comp.lang.c as one file to simplify things,
    >>but yes these declarations should be in a header file.

    >
    > I haven't read it, but probably they should not be in a header.
    > The only things that go in a header file are the definitions,
    > constants, prototypes etc. that you want to export so that other
    > programs can access your file. Headers are a misnomer - they are
    > not the place to put headings, but they are the place to export
    > linkages.


    In the snipped context, I referred to function prototypes which
    probably still are also declarations :)

    Cheers
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
     
    Michael Mair, Feb 18, 2008
    #10
  11. CBFalconer Guest

    wrote:
    > CBFalconer <> wrote:
    >
    >> Actually, the whole sequence is:
    >>
    >> N869 Last draft before std issuance
    >> C99 std The thing itself
    >> N1124 plus TC1 and TC2
    >> N1256 plus TC3

    >
    > You left out:
    >
    > N949 plus TC1


    No such thing appears on
    <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n949.pdf>

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.



    --
    Posted via a free Usenet account from http://www.teranews.com
     
    CBFalconer, Feb 19, 2008
    #11
  12. Guest

    On Feb 17, 2:44 am, CBFalconer <> wrote:
    > wrote:
    > > Michael Mair <> wrote:

    >
    > ... snip ...
    >
    > >> The following belongs in a header file.

    >
    > > I chose to post it to comp.lang.c as one file to simplify things,
    > > but yes these declarations should be in a header file.

    >
    > I haven't read it, but probably they should not be in a header.
    > The only things that go in a header file are the definitions,

    A function declaration is
    int foo(int);
    A function definition is
    int foo(int) { return 0; }
    The former, I have seen on most header files; the latter is quite
    exceptional.

    > constants, prototypes etc. that you want to export so that other
    > programs can access your file. Headers are a misnomer - they are
    > not the place to put headings, but they are the place to export
    > linkages.

    The rest I agree.
     
    , Feb 20, 2008
    #12
    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. Jeff

    [OT?] xmalloc

    Jeff, Jul 1, 2003, in forum: C Programming
    Replies:
    10
    Views:
    1,238
    Dan Pop
    Jul 7, 2003
  2. Malcolm McLean

    xmalloc

    Malcolm McLean, Jun 23, 2007, in forum: C Programming
    Replies:
    52
    Views:
    1,785
    Ben Pfaff
    Jun 27, 2007
  3. Kelsey Bjarnason

    xmalloc string functions

    Kelsey Bjarnason, Jan 27, 2008, in forum: C Programming
    Replies:
    240
    Views:
    3,487
  4. Tim Hollingsworth

    Multi-threaded C++, new, and xmalloc

    Tim Hollingsworth, Nov 23, 2006, in forum: Ruby
    Replies:
    4
    Views:
    122
    Paul Brannan
    Nov 24, 2006
Loading...

Share This Page