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