W
Wynand Winterbach
I think every C programmer can relate to the frustrations that malloc
allocated arrays bring. In particular, I've always found the fact that
the size of an array must be stored separately to be a nightmare.
There are of course many solutions, but they all end up forcing you to
abandon the array syntax in favour of macros or functions.
Now I have two questions - one is historical, and the other practical.
1.) Surely malloc (and friends) must store the size allocated for a
particular memory allocation, if malloc is to know how much to
deallocate when a free() occurs? Thus, why was the C library designed
in such a fashion as not to make this information available? Or I am
seriously missing something here?
2.) Why not store the size of the array in its first four bytes (or
first sizeof( size_t ) bytes ), and then shift the pointer to the
array on by four bytes? Thus one has:
first 4 bytes everything else
[ size ][ data ]
/\
void * blah ---'
Then it should behave as a "normal" array, with the added advantage of
knowing its size. The reason I have doubts here, is that if this was
such a good idea, I'm sure it would already have been widely used. Any
compelling reason for avoiding this? This is a bit of hackery, but the
hackery will be confined to the functions for allocating, resizing and
checking the size of the array.
The code could work as follows:
void*
malloc_array( size_t element_size, size_t items )
{
size_t sz = element_size * items;
void* result = malloc( sz + sizeof( size_t ) ); /* allocate memory
for array and for size chunk */
*((size_t*) result) = items; /* assign the size to
the first few bytes */
return sz + sizeof( size_t ); /* return a pointer
to the array pointing just beyond size chunk */
}
size_t
sizeof_array( void *array )
{
return *( (size_t*) (array - sizeof( size_t )) );
}
This technique of course could also be used to store the byte size of
the elements in the array. Oh yes, and in order to detect whether the
size value was corrupted by accidentally writing over it, one could
use a magic number (which would again be added by the same technique),
which could be consulted with debugging code.
allocated arrays bring. In particular, I've always found the fact that
the size of an array must be stored separately to be a nightmare.
There are of course many solutions, but they all end up forcing you to
abandon the array syntax in favour of macros or functions.
Now I have two questions - one is historical, and the other practical.
1.) Surely malloc (and friends) must store the size allocated for a
particular memory allocation, if malloc is to know how much to
deallocate when a free() occurs? Thus, why was the C library designed
in such a fashion as not to make this information available? Or I am
seriously missing something here?
2.) Why not store the size of the array in its first four bytes (or
first sizeof( size_t ) bytes ), and then shift the pointer to the
array on by four bytes? Thus one has:
first 4 bytes everything else
[ size ][ data ]
/\
void * blah ---'
Then it should behave as a "normal" array, with the added advantage of
knowing its size. The reason I have doubts here, is that if this was
such a good idea, I'm sure it would already have been widely used. Any
compelling reason for avoiding this? This is a bit of hackery, but the
hackery will be confined to the functions for allocating, resizing and
checking the size of the array.
The code could work as follows:
void*
malloc_array( size_t element_size, size_t items )
{
size_t sz = element_size * items;
void* result = malloc( sz + sizeof( size_t ) ); /* allocate memory
for array and for size chunk */
*((size_t*) result) = items; /* assign the size to
the first few bytes */
return sz + sizeof( size_t ); /* return a pointer
to the array pointing just beyond size chunk */
}
size_t
sizeof_array( void *array )
{
return *( (size_t*) (array - sizeof( size_t )) );
}
This technique of course could also be used to store the byte size of
the elements in the array. Oh yes, and in order to detect whether the
size value was corrupted by accidentally writing over it, one could
use a magic number (which would again be added by the same technique),
which could be consulted with debugging code.