where to allocate memory

Discussion in 'C Programming' started by gc, Nov 6, 2003.

  1. gc

    gc Guest

    I am writing a function that given nx1 vector a and a nx1 b solves a
    system of equations f(a,c)=b for a nx1 c.

    While writing the function:
    1] Should I allocate the memory for c within the function and return
    the allocated memory?
    something that leads to
    double *solve(const double *a,const double *b,int n)
    {
    double *c;
    /*blah blah*/
    c=malloc(n*sizeof(*c));
    /*blah blah*/
    return c;
    }

    or,

    2] Should I allocate the memory outside the function and then pass it
    as a parameter?

    void solve(const double *a,const double *b,double *c,int n);


    /****/
    c=malloc(n*sizeof(*c));
    solve(a,b,c,n);
     
    gc, Nov 6, 2003
    #1
    1. Advertising

  2. gc

    Simon Biber Guest

    "gc" <> wrote:
    > While writing the function:
    > 1] Should I allocate the memory for c within the function and
    > return the allocated memory?
    > or,
    > 2] Should I allocate the memory outside the function and then
    > pass it as a parameter?


    Both are valid solutions in C. I generally prefer the latter form
    as it gives the caller more control over how they want to manage
    the memory. (Perhaps using an automatic array rather than malloced
    storage). I think it also looks cleaner to have the malloc and its
    corresponding free in the same function.

    double a = malloc(n * sizeof *c);
    double b = malloc(n * sizeof *c);

    double c = malloc(n * sizeof *c);
    if(a && b && c)
    {
    /* set up a, b */
    solve(a, b, c, n);
    /* use c */
    free(a);
    free(b);
    free(c);
    }

    Or:

    double a[] = {1, 2 /* ... */};
    double b[] = {1, 2 /* ... */};
    double c[sizeof a / sizeof *a];
    solve(a, b, c, sizeof a / sizeof *a);
    /* use c */

    --
    Simon.
     
    Simon Biber, Nov 6, 2003
    #2
    1. Advertising

  3. gc wrote:

    > I am writing a function that given nx1 vector a and a nx1 b solves a
    > system of equations f(a,c)=b for a nx1 c.
    >
    > While writing the function:
    > 1] Should I allocate the memory for c within the function and return
    > the allocated memory?


    If you like.

    > something that leads to
    > double *solve(const double *a,const double *b,int n)
    > {
    > double *c;
    > /*blah blah*/
    > c=malloc(n*sizeof(*c));


    if(c != NULL)
    {

    > /*blah blah*/


    }

    > return c;
    > }
    >
    > or,
    >
    > 2] Should I allocate the memory outside the function and then pass it
    > as a parameter?


    If you like.

    >
    > void solve(const double *a,const double *b,double *c,int n);
    >
    >
    > /****/
    > c=malloc(n*sizeof(*c));
    > solve(a,b,c,n);




    It's a design decision that only you can make. But I would look at it this
    way - if you're going to need many solutions to different problems to exist
    at the same time, then probably you'll find it more convenient for the
    function to allocate the memory. If, on the other hand, your typical usage
    scenario is that you solve /one/ problem, then another, then another,
    without the solutions needing to co-exist, then it may be handier to pass
    in the memory. That way, you can re-use it if you wish. Alternatively, pass
    in a pointer to the memory, and get solve() to resize it as appropriate.

    --
    Richard Heathfield :
    "Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
    C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
    K&R answers, C books, etc: http://users.powernet.co.uk/eton
     
    Richard Heathfield, Nov 6, 2003
    #3
  4. gc

    Roose Guest

    If there's no good reason to allocate it in the function, then I prefer to
    have the caller allocate. You might always remember to free, but others
    might not. If you make them write the malloc, they won't forget.

    Also, the caller allocating is slightly better from a code reuse point of
    view. Your solver is now tied to malloc, whereas some people use different
    memory management schemes. I have no idea what system you're on, but if you
    use multiple heaps or anything like that, you want to have the caller
    allocate.

    But if you're just writing some small, quick app, there's probably no
    difference.

    "gc" <> wrote in message
    news:...
    > I am writing a function that given nx1 vector a and a nx1 b solves a
    > system of equations f(a,c)=b for a nx1 c.
    >
    > While writing the function:
    > 1] Should I allocate the memory for c within the function and return
    > the allocated memory?
    > something that leads to
    > double *solve(const double *a,const double *b,int n)
    > {
    > double *c;
    > /*blah blah*/
    > c=malloc(n*sizeof(*c));
    > /*blah blah*/
    > return c;
    > }
    >
    > or,
    >
    > 2] Should I allocate the memory outside the function and then pass it
    > as a parameter?
    >
    > void solve(const double *a,const double *b,double *c,int n);
    >
    >
    > /****/
    > c=malloc(n*sizeof(*c));
    > solve(a,b,c,n);
     
    Roose, Nov 6, 2003
    #4
  5. gc

    rihad Guest

    On Thu, 6 Nov 2003 18:01:06 +1100, "Simon Biber" <> wrote:

    >double a = malloc(n * sizeof *c);
    >double b = malloc(n * sizeof *c);
    >
    >double c = malloc(n * sizeof *c);
    >if(a && b && c)
    >{
    > /* set up a, b */
    > solve(a, b, c, n);
    > /* use c */
    > free(a);
    > free(b);
    > free(c);
    >}


    What if a failed, you wouldn't be freeing the other guys? I still prefer the
    "goto to the function trailer" approach.
     
    rihad, Nov 6, 2003
    #5
  6. gc

    rihad Guest

    On Thu, 06 Nov 2003 12:48:51 +0400, rihad <> wrote:

    >On Thu, 6 Nov 2003 18:01:06 +1100, "Simon Biber" <> wrote:
    >
    >>double a = malloc(n * sizeof *c);
    >>double b = malloc(n * sizeof *c);
    >>
    >>double c = malloc(n * sizeof *c);


    "Oh, *pointers* are simple - it's *typing* that's difficult. :)"

    >>if(a && b && c)
    >>{
    >> /* set up a, b */
    >> solve(a, b, c, n);
    >> /* use c */
    >> free(a);
    >> free(b);
    >> free(c);
    >>}

    >
    >What if a failed, you wouldn't be freeing the other guys? I still prefer the
    >"goto to the function trailer" approach.


    Namely:
    double a = malloc(n * sizeof *c);
    double b = malloc(n * sizeof *c);

    double c = malloc(n * sizeof *c);
    if(!(a && b && c))
    goto nomem;
    /* set up a, b */
    solve(a, b, c, n);
    /* use c */

    nomem:
    free(a);
    free(b);
    free(c);
    }
     
    rihad, Nov 6, 2003
    #6
  7. gc

    pete Guest

    gc wrote:
    >
    > I am writing a function that given nx1 vector a and a nx1 b solves a
    > system of equations f(a,c)=b for a nx1 c.
    >
    > While writing the function:
    > 1] Should I allocate the memory for c within the function and return
    > the allocated memory?


    > or,
    >
    > 2] Should I allocate the memory outside the function and then pass it
    > as a parameter?


    I prefer #2.
    1 It's easier to remember to write a call to free,
    if you've just written the call to malloc.
    2 If the function is recursive, you save a lot of allocating.
    3 The function is more versatile.
    It's possible that sometime, you may get a chance to pass
    the function an automatic array, instead.


    --
    pete
     
    pete, Nov 6, 2003
    #7
  8. gc

    Al Bowers Guest

    rihad wrote:
    > On Thu, 06 Nov 2003 12:48:51 +0400, rihad <> wrote:
    >
    >
    >>On Thu, 6 Nov 2003 18:01:06 +1100, "Simon Biber" <> wrote:
    >>
    >>
    >>>double a = malloc(n * sizeof *c);
    >>>double b = malloc(n * sizeof *c);
    >>>
    >>>double c = malloc(n * sizeof *c);

    >
    >
    > "Oh, *pointers* are simple - it's *typing* that's difficult. :)"
    >
    >
    >>>if(a && b && c)
    >>>{
    >>> /* set up a, b */
    >>> solve(a, b, c, n);
    >>> /* use c */
    >>> free(a);
    >>> free(b);
    >>> free(c);
    >>>}

    >>
    >>What if a failed, you wouldn't be freeing the other guys? I still prefer the
    >>"goto to the function trailer" approach.


    Yes, that should be a concern which this code does not handle.
    However, the code snippet above will not even compile for other
    reasons.
    >
    >
    > Namely:
    > double a = malloc(n * sizeof *c);
    > double b = malloc(n * sizeof *c);
    >
    > double c = malloc(n * sizeof *c);


    Why do you repeat the flawed code?
    a, b, c should all be a pointer type.
    The variable c is being used before it has been declared.
    Namely: A lot of errors in this short snippet of code.

    > if(!(a && b && c))
    > goto nomem;
    > /* set up a, b */
    > solve(a, b, c, n);
    > /* use c */
    >
    > nomem:
    > free(a);
    > free(b);
    > free(c);
    > }
    >


    There is no need to do a goto here. Simply free a, b, and c
    in the "trailer".

    #include <stdio.h>
    #include <math.h>
    #include <stdlib.h>

    void solve(double *a, double *b, double *c, double n);

    int main(void)
    {
    double n = 9000.00;
    double *a = malloc(sizeof *a);
    double *b = malloc(sizeof *b);
    double *c = malloc(sizeof *c);

    if(a && b && c)
    {
    solve(a, b, c, n);
    printf("*a = %f\n*b = %f\n*c = %f\n",*a,*b,*c);
    }
    free(a);
    free(b);
    free(c);
    return 0;
    }

    void solve(double *a, double *b, double *c, double n)
    {
    *a = log(n);
    *b = log10(n);
    *c = *a-*b;
    printf("log(%.2f) = %f\n",n,*a);
    printf("log10(%.2f) = %f\n",n,*b);
    printf("log(%.2f) - log10(%.2f) = %f\n\n", *a, *b,
    log(*a)-log(*b));
    return;
    }

    --
    Al Bowers
    Tampa, Fl USA
    mailto: (remove the x to send email)
    http://www.geocities.com/abowers822/
     
    Al Bowers, Nov 6, 2003
    #8
  9. gc

    Simon Biber Guest

    "rihad" <> wrote:
    > On Thu, 06 Nov 2003 12:48:51 +0400, rihad <> wrote:
    > >On Thu, 6 Nov 2003 18:01:06 +1100, "Simon Biber" <> wrote:
    > >
    > >>double a = malloc(n * sizeof *c);
    > >>double b = malloc(n * sizeof *c);
    > >>
    > >>double c = malloc(n * sizeof *c);

    >
    > "Oh, *pointers* are simple - it's *typing* that's difficult. :)"


    Indeed. Thanks, Richard :-(

    --
    Simon.
     
    Simon Biber, Nov 6, 2003
    #9
  10. (gc) wrote in message news:<>...

    > I am writing a function that given nx1 vector a and a nx1 b solves a
    > system of equations f(a,c)=b for a nx1 c.
    >
    > While writing the function:
    > 1] Should I allocate the memory for c within the function and return
    > the allocated memory?


    <snip code>

    > or,
    >
    > 2] Should I allocate the memory outside the function and then pass it
    > as a parameter?


    <snip>

    you've had quite few answers by now. I'll only add I'd favour 2] by
    the old design rule that every function should do only one thing. Have
    a separate allocator.


    --
    Nick Keighley
     
    Nick Keighley, Nov 6, 2003
    #10
  11. Greetings.

    In article <fwnqb.820$>, Roose wrote:
    > If there's no good reason to allocate it in the function, then I prefer to
    > have the caller allocate.


    To what does "it" refer?

    > "gc" <> wrote in message
    > news:...
    >> 1] Should I allocate the memory for c within the function and return
    >> the allocated memory?


    Oh, I see.

    Please don't top-post.

    Regards,
    Tristan

    --
    _
    _V.-o Tristan Miller [en,(fr,de,ia)] >< Space is limited
    / |`-' -=-=-=-=-=-=-=-=-=-=-=-=-=-=-= <> In a haiku, so it's hard
    (7_\\ http://www.nothingisreal.com/ >< To finish what you
     
    Tristan Miller, Nov 6, 2003
    #11
  12. gc

    Alan Balmer Guest

    On 5 Nov 2003 20:54:57 -0800, (gc) wrote:

    >I am writing a function that given nx1 vector a and a nx1 b solves a
    >system of equations f(a,c)=b for a nx1 c.
    >
    >While writing the function:
    >1] Should I allocate the memory for c within the function and return
    >the allocated memory?
    >something that leads to

    <snip>
    >or,
    >
    >2] Should I allocate the memory outside the function and then pass it
    >as a parameter?


    It will work either way, but in general, I'd recommend the second
    approach as being less error-prone. Rule of thumb: whenever possible,
    malloc and the associated free should be in the same scope.

    --
    Al Balmer
    Balmer Consulting
     
    Alan Balmer, Nov 6, 2003
    #12
  13. gc

    James Hu Guest

    On 2003-11-06, Roose <> wrote:
    ....
    [top posting fixed]
    ....
    > "gc" <> wrote in message
    > news:...
    >> I am writing a function that given nx1 vector a and a nx1 b solves a
    >> system of equations f(a,c)=b for a nx1 c.
    >>
    >> While writing the function:
    >> 1] Should I allocate the memory for c within the function and return
    >> the allocated memory?
    >> something that leads to
    >> double *solve(const double *a,const double *b,int n)
    >> {
    >> double *c;
    >> /*blah blah*/
    >> c=malloc(n*sizeof(*c));
    >> /*blah blah*/
    >> return c;
    >> }
    >>
    >> or,
    >>
    >> 2] Should I allocate the memory outside the function and then pass it
    >> as a parameter?
    >>
    >> void solve(const double *a,const double *b,double *c,int n);
    >>
    >>
    >> /****/
    >> c=malloc(n*sizeof(*c));
    >> solve(a,b,c,n);

    >
    > If there's no good reason to allocate it in the function, then I prefer to
    > have the caller allocate. You might always remember to free, but others
    > might not. If you make them write the malloc, they won't forget.


    Please don't top post in this newsgroup. Thanks.

    > Also, the caller allocating is slightly better from a code reuse point of
    > view. Your solver is now tied to malloc, whereas some people use different
    > memory management schemes. I have no idea what system you're on, but if you
    > use multiple heaps or anything like that, you want to have the caller
    > allocate.


    This is not necessarily true. The provider of the library can expose
    an interface to allow the client of the library to tweak the allocator.

    /*
    * By default, the library uses malloc and free to handle its
    * dynamic memory allocation requirements. If you wish to
    * change the default allocator, use this function. Both
    * m (e.g., malloc) and f (e.g., free) must point to valid
    * functions. If either is NULL, no change will take effect.
    */
    void set_allocator(void *(*m)(size_t), void (*f)(void *));

    This could be useful if the library is using a data structure that
    requires multiple allocations. If the library does not want to
    expose the nature of the data structure to the library client, then
    the library has to be the one to construct the data structure.

    It could also be useful if the library is utilizing a reference
    counting mechanism, where it is the job of the reference release
    function to reap any allocated resources when the count gets to
    0.

    The library might maintain pointers, e.g.:

    /* mylib.c */
    #include <stdlib.h>
    /* ... */
    static void *(*mymalloc)(size_t) = malloc;
    static void (*myfree)(void *) = free;
    /* ... */
    void
    set_allocator(void *(*m)(size_t), void (*f)(void *))
    {
    if (m == 0 || f == 0) {
    return;
    }
    mymalloc = m;
    myfree = f;
    }

    -- James
     
    James Hu, Nov 6, 2003
    #13
    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. Roedy Green
    Replies:
    3
    Views:
    3,280
    Roedy Green
    Aug 14, 2003
  2. sks_cpp
    Replies:
    7
    Views:
    396
    Jerry Coffin
    Jul 4, 2003
  3. Curt
    Replies:
    37
    Views:
    1,195
    Alexander Terekhov
    Jul 26, 2003
  4. OlgaM
    Replies:
    1
    Views:
    421
    Mike Wahler
    Oct 10, 2003
  5. Alan Gifford
    Replies:
    4
    Views:
    397
    tom_usenet
    Oct 27, 2003
Loading...

Share This Page