realloc questions

Mark Moraes moraes at cs.toronto.edu
Fri Mar 2 22:06:14 AEST 1990


Sigh.  After two incorrect/partial answers, I couldn't resist.

When posting code fragments that you have problems with, it might be a
good idea to make sure they compile first.  Also, please pass them
through either lint or an ANSI C compiler with good warnings and
prototyped header files.  (If your C environment has neither, then
you're working in an unsupportive environment and are asking for
trouble -- lint is a good friend.  People who don't realize how much
of a friend it can be should see refs 1 and 2 below)

The code posted in <4563 at rouge.usl.edu> a) wouldn't compile
b) produced several serious lint errors (marked with ? and annotating
comments below) c) contained at least one serious logical error.  A
good example of how people seem to be confused about C pointers,
arrays, malloc and realloc.

    typedef struct a 
            { int row, col; long **arr} A;
    A *temp;

    temp=(A *) calloc (1, sizeof(A));  /* then initialize row and col ... */
    A->arr=(long *)calloc (A->row, sizeof(long *));
                 ?  /* cast to long **, not (long *) */
    for (j=0;j<A->row;j++)
       A->arr[j] = calloc(col,sizeof(long));

   A->arr=(long *) realloc ((char *)&A->arr, new_row*sizeof(long *));
               ?                    ? /* No need for & */
   for (j=0;j<A->new_row;j++)
                 ???????  /* 
			   * The pointers in temp->arr[] from row to
			   * new_row will contain undefined values,
			   * since realloc(temp->arr) does not zero the
			   * grown space.  All realloc guarantees is
			   * that the first MIN(old size, new size)
			   * bytes will contain exactly what they did
			   * before the realloc. Also, many reallocs do not
			   * guarantee ANSI C semantics of realloc(NULL,
			   * n) => malloc(n)
			   */
       A->arr[j] = realloc(new_col,sizeof(long));
                           ???????  /* Ouch!  What are you reallocing? */

The following is a version that at least passes a C compiler and lint
cleanly (modulo usual warnings about pointer alignment) -- it should
work. Run through cb -s for good measure.  (To keep it reasonably
short, I've committed the heinous "Can't happen" sin of not checking
the calloc/realloc error returns.  Any self respecting production
program would check those, of course)

typedef char * pointer;	    /* void * in ANSI C */

extern pointer calloc();
extern pointer realloc();
extern void free();	    /* returns int in older implementations */

typedef struct {
    unsigned int row, col;
    long **arr;
} A;

int
main()
{
    A *temp;
    unsigned int new_col, new_row;
    int j;

    temp = (A *) calloc ((unsigned) 1, sizeof(A));
    /* then initialize row and col ... */
    temp->row = 5;
    temp->col = 10;
    temp->arr = (long **) calloc (temp->row, sizeof(long *));
    for (j = 0; j < temp->row; j++)
       temp->arr[j] = (long *) calloc(temp->col, sizeof(long));

    /*
     * now you can access temp->arr[j][k] for 0 <= j < temp->row and 0
     * <= k < temp->col.
     */
    new_row = 10;
    new_col = 20;
    /* grow vector of pointers to rows */
    temp->arr = (long **) realloc ((pointer)temp->arr,
				   new_row * sizeof(long *));
    /*
     * grow old rows -- if new_row could be less than temp->row, we'd
     * have a to be a little more careful
     */
    for (j = 0; j < temp->row; j++)
	temp->arr[j] = (long *) realloc((pointer) temp->arr[j],
					new_col * sizeof(long));
    /* allocate new rows */
    for(j = temp->row; j < new_row; j++)
	temp->arr[j] = (long *) calloc(new_col, sizeof(long));

    /* 
     * just as a tutorial (xref the Turbo C malloc thread), we free the
     * arrays.  Remember the simple rule -- if you didn't get the
     * pointer from malloc/calloc or realloc, you CANNOT free it.
     */
    for(j = 0; j < new_row; j++)
	free((pointer) temp->arr[j]);
    free((pointer) temp->arr);
    free((pointer) temp);
    return 0;
}

Refs:

1. Ian Darwin and Geoff Collyer, "Can't Happen or /* NOTREACHED */ or
Real Programs Dump Core" USENIX Association Winter Conference, Dallas
1985 Proceedings.

2. Ian Darwin, "Checking C Programs with lint", O'Reilly Books.



More information about the Comp.lang.c mailing list