John said:
ORCdarrayfree is used to free 2-d array allocated by malloc.
The src is:
/* ORCdarraynew function return void** ,
and ORCdarrayfree should get void** to
make these 2 functions to be used in
allocating integer, char, and other
customize type */
void**
ORCdarraynew (int row, int col, int size)
These should probably be size_t rather than int.
{
void **arr;
arr = (void **) malloc (sizeof(void *) * row + size * row * col);
Casting the result of malloc is unnecessary and can mask errors.
if ( arr != NULL ) {
void *head;
head = (void *) arr + sizeof(void *) * row;
memset (arr, 0, sizeof(void *) * row + size * row * col);
while (row--) {
arr[row] = head + size * row * col;
}
}
return arr;
} /* End of ORCdarraynew*/
So you're allocating a chunk of memory consisting of an array of void*
pointers, immediately followed by a 2-dimensional array of some
arbitrary data, where each of the initial void* pointers points to a
row in the 2d array. Interesting. Let's call these two sections the
"index" and the "table", respectively.
You're making some non-portable assumptions, though.
The memset call zeros both the index and the table. The former is
useless, since you immediately initialize the table anyway. Zeroing
the table may or may not be sensiple, depending on what data you're
storing. Remember that null pointers aren't necessarily all-bits-zero
(though they commonly are).
You're also assuming that the table will be properly aligned.
Consider a system where void* is 32-bit aligned, double is 64-bit
aligned, and you want to allocate a table of doubles with an odd
number of rows.
void
ORCdarrayfree (void **arr)
{
if ( arr != NULL ) {
free (arr);
arr = NULL;
}
} /* End of ORCdarrayfree*/
Note that the "arr != NULL" test is unnecessary; free() does nothing
if you give it a null pointer argument. And setting arr to NULL is
useless; you're just clobbering a local object. You might want to do
"*arr = NULL;" -- or you might just want to leave it alone.
We can call them like:
int **p;
p = (int**)ORCdarraynew(nrows, ncols, sizeof(int));
ORCdarrayfree(p);
So the parameter of ORCdarrayfree will be converted from int** to
void**.
While, the gcc compiler give me a warning:
warning: passing arg 1 of `ORCdarrayfree' from
incompatib
le pointer type
gcc is correct; the pointer types are incompatible.
I think you need to allocate the index and the table in two separate
calls to malloc().
Here's a thought. Allocate row+1 void* elements for the index.
Allocate size*row*col bytes for the table; using a separate call to
malloc guarantees proper alignment. Store the address of the table in
the 0th element of the index, then return the address of the 1st
element. ORCdarrayfree can then index backwards to obtain the address
of the table, free the table, then free the index.
I haven't completely thought this through. This approach should be
type-safe, but I think you might have some problems with indexing
(e.g., p[x][y]).