allbery@ncoast.UUCP (Brandon Allbery) (06/22/86)
Expires: Quoted from <2081@umcp-cs.UUCP> ["Re: get size of malloc'd object"], by chris@umcp-cs.UUCP... +--------------- | In article <2206@peora.UUCP>, jer@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@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)