realloc questions

Mark Brader msb at sq.sq.com
Tue Mar 6 16:36:48 AEST 1990


[Karl Heuer: if you see this, let me know.]
[Anyone: if you see this twice, my apologies.]

> >   temp->arr=(long *) realloc ((char *)&temp->arr, new_row*sizeof(long *));
> >   for (j=0;j<temp->new_row;j++)
> >       temp->arr[j] = realloc(new_col,sizeof(long));

> You're re-allocating temp->arr before you re-allocate temp->arr[j]!
> Just switch the order of the realloc() calls and you should be fine.

No, it's more complicated than that.   You only want to use realloc() on
only those rows that existed and will continue to exist.  If there
are new rows, you have to malloc() them.  (Well, there are other ways
to arrange it, but they aren't any easier.)  Conversely, for the ones
that are ceasing to exist, you want to free() them.  Also, the first
call to realloc() is has an extra & and its result is wrongly cast, and
the second call is worse, having the arguments of calloc() instead of
realloc().  And temp->new_row is also wrong.

(Please let your compilers get the syntax errors out of your code before
you post it!  The code below has been compiled and (lightly) tested.)

Try this:

	    /* if number of rows is about to shrink, get rid of old ones
	     * (else, the loop will iterate 0 times) */
	for (j = new_row; j < temp->row; ++j)
		free ((char *) temp->arr[j]);

	    /* adjust number of rows */
	temp->arr = (long **) realloc ((char *) temp->arr,
						new_row * sizeof (long *));

	    /* if number of rows has just grown, allocate new ones
	     * (else, the loop will iterate 0 times) */
	for (j = temp->row; j < new_row; ++j)
		temp->arr[j] = (long *) malloc (new_col * sizeof (long));

	    /* adjust length of rows that exist and will continue to exist
	     * (while the three operations above must be in the order shown,
	     * this one could go at any point above or below them) */
	for (j = 0; j < temp->row && j < new_row; ++j)
		temp->arr[j] = (long *) realloc ((char *) temp->arr[j],
						new_col * sizeof (long));

	    /* update row and column information */
	temp->row = new_row;
	temp->col = new_col;

Another approach is to just free the whole structure and start over.
Since the original posting used calloc(), not malloc(), to allocate
the space, it may have been important that the array be initialized
so zeroes.  If realloc() enlarges the allocated space, the added
space is uninitialized.  In the above, I have elected to assume that
no initialization was really desired, and used malloc() and realloc().
If initialization IS really desired, the malloc(a*b) call should be
changed to calloc(a,b), and the last for-loop should become:

	for (j = 0; j < temp->row && j < new_row; ++j) {
		register int k;
		temp->arr[j] = (long *) realloc ((char *) temp->arr[j],
						new_col * sizeof (long));
		for (k = temp->col; k < new_col; ++k)
			temp->arr[j][k] = 0;
	}

or the equivalent thereof.

Depending on how your malloc() works, starting over may give better
results anyway, by maximizing malloc()'s chances to coalesce the
allocated chunks of memory.  Then again, it may not.


-- 
Mark Brader		     "I always pass on good advice.  It's the only thing
SoftQuad Inc., Toronto	      to do with it.  It is never any use to oneself."
utzoo!sq!msb, msb at sq.com 	-- Lord Goring  (Oscar Wilde: An Ideal Husband)

This article is in the public domain.



More information about the Comp.lang.c mailing list