Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   malloc inside function (I know... I *did* search google first ;) (http://www.velocityreviews.com/forums/t439178-malloc-inside-function-i-know-i-did-search-google-first.html)

spasmous@yahoo.com 08-23-2005 07:43 PM

malloc inside function (I know... I *did* search google first ;)
 
main()
{
float * f;
initialize_f(f);

// ...use f for processing

free(f);
}

void initialize_f(float * f)
{
long n = 100;
f = (float*)malloc(n*sizeof(float));

f[1] = ... // etc. fill f array here
}



The size of the array is only known once initialize_f() is called so I
can't allocate it in main(). Please can someone tell me if f will be
initialized correctly by this code? Thanks :)


Charles M. Reinke 08-23-2005 08:22 PM

Re: malloc inside function (I know... I *did* search google first ;)
 
<spasmous@yahoo.com> wrote in message
news:1124826226.583391.279940@g43g2000cwa.googlegr oups.com...

You are missing a necessary header here:
#include <stdlib.h>
You're also missing a prototype for a funtion called in main(), try:
void initialize_f(float *f);

> main()


This should be:
int main(void)
Please refer to the c.l.c FAQ at http://www.faqs.org/faqs/C-faq/faq/ (which
you apparently DIDN'T find while googling), question #11.12a.

> {
> float * f;


Why use (float) instead of (double)?

> initialize_f(f);
>
> // ...use f for processing
>
> free(f);


main() returns an int, you are missing something like:
return 0;

> }
>
> void initialize_f(float * f)
> {
> long n = 100;
> f = (float*)malloc(n*sizeof(float));


Casting the return value of malloc() is highly discouraged; see c.l.c FAQ
#7.7. In fact, in this case the absence of the unneccesary cast may have
given you a hint at compile time that you had forgotten to include a
required header file.

>
> f[1] = ... // etc. fill f array here


You do realize, of course, that arrays in C start at index 0--what happens
to f[0] in your code?

> }
>
>
>
> The size of the array is only known once initialize_f() is called so I
> can't allocate it in main(). Please can someone tell me if f will be
> initialized correctly by this code? Thanks :)
>


I don't see any problems with the initialization of "f" in this code.
However your initialize_f() function should probably supply "n" as its
return value so that its size can be known in main(). I would write it
something like this:
/* Untested code follows */
long initialize_f(float *f) {
int i;
long n = 100;
f = malloc((size_t)n * sizeof *f);

for(i=0; i<n; i++) {
f[i] = 0; /* or whatever initialization value you want */
} /* for i */

return n;
} /* initialize_f */

-Charles



Kevin J. Phillips 08-23-2005 08:28 PM

Re: malloc inside function (I know... I *did* search google first ;)
 
spasmous wrote:
> main()
> {
> float * f;
> initialize_f(f);
>
> // ...use f for processing
>
> free(f);
> }
>
> void initialize_f(float * f)
> {
> long n = 100;
> f = (float*)malloc(n*sizeof(float));
>
> f[1] = ... // etc. fill f array here
> }
>
> The size of the array is only known once initialize_f() is called so I
> can't allocate it in main(). Please can someone tell me if f will be
> initialized correctly by this code? Thanks :)


No, that won't work because C is call by value. 'initialize_f'
gets a copy of 'f'. The copy is updated by the call to malloc()
but when the function returns, the value in the copy is lost.
You have to send initialize_f() a pointer to 'f'.
Try something like this instead.
Its untested and uncompiled, but it gets the idea across:

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

void initialize_f(float **f, long *n);

int main(void)
{
float *f;
long n;

initialize_f(&f, &n);
if (f == NULL)
exit(EXIT_FAILURE);

/* use f for processing ...
*
* if (f[0] < 3.14159) printf("almost pi!\n");
*/
...

/* All done, cleanup and quit */
free(f);

return 0;
}


void initialize_f(float **f, long *n)
{
*n = 100;
*f = malloc(n * sizeof **f);
if (*f == NULL)
{
fprintf(stderr, "malloc() failed\n");
return;
}

/* Initialize elements of f...
* (*f)[0] = 3.14159;
* (*f)[1] = ...
* ...
* (*f)[n-1] = ...
*/

}

Emmanuel Delahaye 08-23-2005 08:29 PM

Re: malloc inside function (I know... I *did* search google first ;)
 
spasmous@yahoo.com wrote on 23/08/05 :
> void initialize_f(float * f)
> {
> long n = 100;
> f = (float*)malloc(n*sizeof(float));


You are modifying the value of a parameter. This often is the sign for
a bad design. Think more and you'll see why.

Note: parameters are passed by value in C.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"It's specified. But anyone who writes code like that should be
transmogrified into earthworms and fed to ducks." -- Chris Dollin CLC



Eric Sosman 08-23-2005 08:29 PM

Re: malloc inside function (I know... I *did* search google first;)
 


spasmous@yahoo.com wrote:
> main()
> {
> float * f;
> initialize_f(f);
>
> // ...use f for processing
>
> free(f);
> }
>
> void initialize_f(float * f)
> {
> long n = 100;
> f = (float*)malloc(n*sizeof(float));
>
> f[1] = ... // etc. fill f array here
> }
>
>
>
> The size of the array is only known once initialize_f() is called so I
> can't allocate it in main(). Please can someone tell me if f will be
> initialized correctly by this code? Thanks :)


It will not. This is Question 4.8 in the comp.lang.c
Frequently Asked Questions (FAQ) list

http://www.eskimo.com/~scs/C-faq/top.html

--
Eric.Sosman@sun.com


Martin Ambuhl 08-23-2005 08:33 PM

Re: malloc inside function (I know... I *did* search google first;)
 
spasmous@yahoo.com posted some error-intensive "code" which demonstrated
that he had not
1) followed the newsgroup before posting,
2) checked the FAQ before posting, or even
3) looked in a basic C text before posting:
> main()
> {
> float * f;
> initialize_f(f);
>
> // ...use f for processing
>
> free(f);
> }
>
> void initialize_f(float * f)
> {
> long n = 100;
> f = (float*)malloc(n*sizeof(float));
>
> f[1] = ... // etc. fill f array here
> }
>


I wrote a long post going over for what must be the 4000th time the
basic problems with the above. Only after I realized that nobody could
be both this stupid and this antisocial and be a legitimate poster that
I killed my response. This troll only got a nibble from me. He'll have
to try harder to get me to swallow the whole hook.

Kevin J. Phillips 08-23-2005 08:34 PM

Re: malloc inside function (I know... I *did* search google first ;)
 

Crap. Just noticed a mistake.

I wrote:
> *f = malloc(n * sizeof **f);


Should be:
*f = malloc(*n * sizeof **f);


Keith Thompson 08-23-2005 08:35 PM

Re: malloc inside function (I know... I *did* search google first;)
 
spasmous@yahoo.com writes:
> main()
> {
> float * f;
> initialize_f(f);
>
> // ...use f for processing
>
> free(f);
> }
>
> void initialize_f(float * f)
> {
> long n = 100;
> f = (float*)malloc(n*sizeof(float));
>
> f[1] = ... // etc. fill f array here
> }
>
>
>
> The size of the array is only known once initialize_f() is called so I
> can't allocate it in main(). Please can someone tell me if f will be
> initialized correctly by this code? Thanks :)


Calling malloc() inside a function doesn't itself cause any problems,
but this program won't work. The variable f in main() and the
parameter f in initialize_f() are two distinct objects. The parameter
gets the value of f when it's called, but that value isn't passed back
to main(). The parameter might as well be a local variable.

One approach is to pass a pointer to f:

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

void initialize_f(float **f);

int main(void)
{
float *f;
initialize_f(&f);

printf("f[1] = %g\n", f[1]);

free(f);
return 0;
}

void initialize_f(float **f_ptr)
{
long n = 100;
*f_ptr = malloc(n * sizeof **f_ptr);
if (*f_ptr == NULL) {
/* error handling */
}
else {
(*f_ptr)[1] = 123.456;
}
}


Some other changes: I declared initialize_f() before the call. I
added the required headers. In the malloc() call, I didn't
unnecessarily convert the result, and I modified the size expression
so it doesn't explicitly depend on the target type (so the malloc()
call doesn't have to change if the type is changed).

Perhaps a better approach is to return the value from the function:

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

float *initialize_f(void);

int main(void)
{
float *f;
f = initialize_f();

printf("f[1] = %g\n", f[1]);

free(f);
return 0;
}

float *initialize_f(void)
{
float *result;
long n = 100;
result = malloc(n*sizeof *result);
if (result == NULL) {
/* error handling */
}
else {
result[1] = 123.456;
}
return result;
}

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

Charles M. Reinke 08-23-2005 08:36 PM

Re: malloc inside function (I know... I *did* search google first ;)
 
"Charles M. Reinke" <cmreinke@ece.gatech.edu> wrote in message
news:deg0ib$fcb$1@news-int.gatech.edu...
> <spasmous@yahoo.com> wrote in message
> news:1124826226.583391.279940@g43g2000cwa.googlegr oups.com...
>
> You are missing a necessary header here:
> #include <stdlib.h>
> You're also missing a prototype for a funtion called in main(), try:
> void initialize_f(float *f);
>
> > main()

>
> This should be:
> int main(void)
> Please refer to the c.l.c FAQ at http://www.faqs.org/faqs/C-faq/faq/

(which
> you apparently DIDN'T find while googling), question #11.12a.
>
> > {
> > float * f;

>
> Why use (float) instead of (double)?
>
> > initialize_f(f);
> >
> > // ...use f for processing
> >
> > free(f);

>
> main() returns an int, you are missing something like:
> return 0;
>
> > }
> >
> > void initialize_f(float * f)
> > {
> > long n = 100;
> > f = (float*)malloc(n*sizeof(float));

>
> Casting the return value of malloc() is highly discouraged; see c.l.c FAQ
> #7.7. In fact, in this case the absence of the unneccesary cast may have
> given you a hint at compile time that you had forgotten to include a
> required header file.
>
> >
> > f[1] = ... // etc. fill f array here

>
> You do realize, of course, that arrays in C start at index 0--what happens
> to f[0] in your code?
>
> > }
> >
> >
> >
> > The size of the array is only known once initialize_f() is called so I
> > can't allocate it in main(). Please can someone tell me if f will be
> > initialized correctly by this code? Thanks :)
> >

>
> I don't see any problems with the initialization of "f" in this code.
> However your initialize_f() function should probably supply "n" as its
> return value so that its size can be known in main(). I would write it
> something like this:
> /* Untested code follows */
> long initialize_f(float *f) {
> int i;
> long n = 100;
> f = malloc((size_t)n * sizeof *f);
>
> for(i=0; i<n; i++) {
> f[i] = 0; /* or whatever initialization value you want */
> } /* for i */
>
> return n;
> } /* initialize_f */
>
> -Charles
>
>


Of course, I made (at least) 2 errors--f must be passed by address, i.e.
long initialize_f(float **f) {
/* corrected code*/
}
and the return value of malloc should ALWAYS be checked for NULL, i.e.
*f = malloc((size_t)n * sizeof **f);
if(*f==NULL) {
/* error handling code here */
}
else {
/* initialization code here */
}
....

-Charles



Michael Mair 08-23-2005 08:47 PM

Re: malloc inside function (I know... I *did* search google first;)
 
Please post clean standard C code which compiles:

$ gcc -ansi -pedantic -Wall -O malloc.c
malloc.c:2: warning: return type defaults to `int'
malloc.c: In function `main':
malloc.c:4: warning: implicit declaration of function `initialize_f'
malloc.c:6: error: parse error before '/' token
malloc.c: At top level:
malloc.c:12: error: conflicting types for 'initialize_f'
malloc.c:4: error: previous implicit declaration of 'initialize_f' was here
malloc.c: In function `initialize_f':
malloc.c:14: warning: implicit declaration of function `malloc'
malloc.c:16: error: parse error before '...' token

It does not cost more than three extra lines to improve it.

Apart from the // comments being not part of C89 (which I inferred
from your use of main()), they also are considered dangerous in
usenet as they are not stable through a linebreak.

spasmous@yahoo.com wrote:
> main()


#include <stdlib.h>

void initialize_f (float *f);

int main (void)
> {
> float * f;
> initialize_f(f);
>
> // ...use f for processing

/* use f for processing */

>
> free(f);


return 0;
> }
>
> void initialize_f(float * f)
> {
> long n = 100;
> f = (float*)malloc(n*sizeof(float));


f = malloc(n * sizeof *f);

is better C, does not mask the error of forgetting to
#include <stdlib.h> and is stable through a type change
of f.

>
> f[1] = ... // etc. fill f array here


You forgot a comment about safety checks on the return value
of malloc() or the actual checks.

f[0] = 0.0F;
/* etc fill f array here */
> }
>
> The size of the array is only known once initialize_f() is called so I
> can't allocate it in main(). Please can someone tell me if f will be
> initialized correctly by this code? Thanks :)


No.
If you want some object O of type T modified by a function,
you do not pass O but the address of O (i.e. a T* argument).
Otherwise, you only have a copy of O for which all steps
you deem necessary are performed -- but this copy of O dies
after the function is left and the original O is unchanged.

So, you want to pass &f to initialize_f, which consequently
has a float** parameter.

Finally, if you really work with array-like semantics for f,
it is better to pass the size info out of initialize_f(),
e.g. as a return value.

#include <stdlib.h>

size_t initialize_f (float **fptr);

int main (void)
{
float *f;
size_t fsize;

if (0 == (fsize = initialize_f(&f))) {
/* error handling */
}

/* use f */

free(f);

return 0;
}

size_t initialize_f (float **fptr)
{
size_t i, n = 100;
*fptr = malloc(n * sizeof **fptr);

if (NULL == *fptr) {
/* maybe error handling; cheap alternative: */
return 0;
}

for (i=0; i<n; i++)
(*fptr)[i] = (float)i/n;

return n;
}

Note: float is almost never the right type for floating
point values -- you run relatively early into precision
and rounding error issues at (most of the time) no gain.
Use double by default and float where you need it.


Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.


All times are GMT. The time now is 06:20 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.