malloc with size keeping
Brandon Allbery
allbery at ncoast.UUCP
Mon Jun 23 06:54:51 AEST 1986
Expires:
Quoted from <2081 at umcp-cs.UUCP> ["Re: get size of malloc'd object"], by chris at umcp-cs.UUCP...
+---------------
| In article <2206 at peora.UUCP>, jer at peora.UUCP (J. Eric Roskos) writes:
| >... allocate a sizeof(int) worth of extra space, then store the
| >size of the thing you malloc'ed in the int at the front of the
| >allocated block, advance the pointer past the place where your
| >stored the size, and return that as the pointer to the block you
| >allocated.
| >
| >This approach is portable, simple, and easy to understand. Also
| >it doesn't require any assumptions about what kind of objects are
| >being allocated.
|
| Unfortunately, it is not necessarily portable. I can imagine a
| machine where `double' arguments must be aligned on an eight-byte
| boundary, but integers are only four bytes wide. In this case
| calling the new routine to allocate doubles would result in an
| odd-address-style trap when the returned value is used.
|
| What can be done is this:
+---------------
Lots of code excluded.
The original response had the right idea, but not portable. Here's *my* way
(Change char * to void * if you have it: mine's a broken PCC, so void is
blocked out):
char *mycalloc(count, size)
unsigned count, size; {
char *block;
int inx, off;
inx = (sizeof (unsigned long) + sizeof (char *)) / size;
off = size - sizeof (unsigned long) - sizeof (char *);
if (inx == 0)
inx++;
if (off < 0)
off += sizeof (unsigned long) + sizeof (char *);
if ((block = calloc(count + inx, size)) == (char *) 0)
return (char *) 0;
*((char *) (block + off)) = block;
*((unsigned long *) (block + off + sizeof (char *))) = count * size;
return block + size;
}
myfree(block)
char *block; {
return free(block - sizeof (unsigned long) - sizeof (char *));
}
unsigned mysize(block)
char *block; {
return *((unsigned long *) block - sizeof (unsigned long));
}
This code uses the fact that a pointer may be stored without loss of precision
in some integer value; I assume that (unsigned long) is in fact the longest
integer available. Except where a sign is stored separately, this will be
true. (And in the latter case, the sign can't be used to store a number, so
even then it should hold.) It also uses the fact that calloc() returns
storage aligned to any boundary, although it assumes that the C compiler also
forces struct sizes to be aligned to the size of the largest integer.
I don't worry about porting to unusual architectures, anyway: if I write a
program that needs this kind of stuff, it's going to be even more incompatible
in other areas...
--Brandon
--
ihnp4!sun!cwruecmp!ncoast!allbery ncoast!allbery at Case.CSNET ncoast!tdi2!brandon
(ncoast!tdi2!root for business) 6615 Center St. #A1-105, Mentor, OH 44060-4101
Phone: +01 216 974 9210 CIS 74106,1032 MCI MAIL BALLBERY (part-time)
More information about the Comp.lang.c
mailing list