Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 14 May 2002 02:55:52 +0300
From:      Giorgos Keramidas <keramida@ceid.upatras.gr>
To:        Paul Everlund <tdv94ped@cs.umu.se>
Cc:        freebsd-questions@FreeBSD.ORG
Subject:   Re: C malloc question
Message-ID:  <20020513235552.GB14825@hades.hell.gr>
In-Reply-To: <Pine.GSO.4.33.0205131845160.22929-100000@gren.cs.umu.se>
References:  <Pine.GSO.4.33.0205131845160.22929-100000@gren.cs.umu.se>

next in thread | previous in thread | raw e-mail | index | archive | help
On 2002-05-13 19:06, Paul Everlund wrote:
> Hi all!
> 
> I have a question regarding malloc and returning arrays in C.
> 
> The following C program is an example.

OK, let's see what could be wrong with this.

     1	#include <stdlib.h>
     2	#include <string.h>

You're missing <stdio.h> which is needed for the prototype of printf()
that is used further below (in line 24).

     3
     4	static char *
     5	init(void)
     6	{
     7		char *str;
     8		int i;
     9
    10		str = (char *)malloc(sizeof(char), 128);

You probably meant to write malloc(sizeof(char) * 128) here.  Note the
multiplication that is used.  The malloc() library function doesn't
take two arguments.

    11		for (i = 0; i < 127; i++)
    12			str[i] = "A";
    13		str[i] = '\0';

These three lines can probably be replaced with:

	bzero((void *) str, 128);

or even better, why don't you use calloc() to allocate memory, instead
of malloc()?  This will zero out the allocated memory for you, before
returning the pointer to its start.

    14		return str;
    15	}
    16
    17	int
    18	main(void)
    19	{
    20		int i;
    21
    22		for (i = 0; i < 500000; i++)
    23			init();

You are calling init() 500,000 times, and throwing away the pointer
that init() returns.  This will result in malloc() being called an
equal number of times, but you can not free() the allocated memory
since you didn't save the pointer it will return.  This is bound to
exchaust your memory very quickly.

    24		printf("%s\n", init());
    25		return 0;
    26	}

> This program takes up a lot of malloc'ed memory after a while,
> so how do one return arrays and free memory in the main function
> everytime the array have been used?

By saving init()'s return value in a (char *) and calling free() on
it, when you're done.  For instance...

	int
	main(void)
	{
		int k;
		char *ptr;

		for (k = 0; k < 500000; k++) {
			ptr = init();
			/* Do stuff here with `ptr'. */
			free(ptr);
		}

		return 0;
	}

> I would like to not use fix- ed size arrays, as the real function
> should be general enough to handle all kind of array sizes.

Then pass the size of the array in a parameter.

	#include <sys/types.h>

	char *
	allocdata (size_t nbytes)
	{
		char *p;

		p = (char *) malloc(nbytes * sizeof(char));
		return p;
	}

	int
	main (void)
	{
		char *a;
		char *b;

		a = allocdata(512);
		b = allocdata(1024);

		/* Do something with `a' and `b'. */

		free(a);
		free(b);

		return 0;
	}

Note that allocdata() as it is written above though reveals that your
function is a plain wrapper around the malloc() library function.  You
can throw away the wrapper (saving you an extra function call) and
write this as:

	int
	main (void)
	{
		char *a;
		char *b;

		a = malloc(512 * sizeof(char));
		b = malloc(1024 * sizeof(char));

It is equally clear, and readable.  Some will argue, more readable.

> What is the best solution for this problem?

The one you like most.

-- 
Giorgos Keramidas    - http://www.FreeBSD.org
keramida@FreeBSD.org - The Power to Serve

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-questions" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020513235552.GB14825>