where to allocate memory

G

gc

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);
 
S

Simon Biber

gc said:
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 */
 
R

Richard Heathfield

gc said:
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.
 
R

Roose

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.
 
R

rihad

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.
 
R

rihad

"Oh, *pointers* are simple - it's *typing* that's difficult. :)"
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);
}
 
P

pete

gc said:
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.
 
A

Al Bowers

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

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

Nick Keighley

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?

<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.
 
A

Alan Balmer

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
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.
 
J

James Hu

....
[top posting fixed]
....
gc said:
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
 

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,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top