get size of malloc'd object
Chris Torek
chris at umcp-cs.UUCP
Thu Jun 19 05:12:43 AEST 1986
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:
#include <stdio.h>
/* change all `char *'s to `void *'s in ANSI C */
struct mymem {
struct mymem *m_next; /* linked list */
struct mymem *m_prev; /* doubly, for easy removal */
unsigned m_size; /* size of mem, in bytes */
char *m_mem; /* storage */
};
/* queue head */
static struct mymem m_base = { &m_base, &m_base };
extern char *malloc();
/*
* Allocate some memory, remembering its size.
*/
char *
myalloc(size)
unsigned size;
{
register struct mymem *m;
if ((m = (struct mymem *) malloc(sizeof (*m))) == NULL)
return (NULL);
if ((m->m_mem = malloc(size)) == NULL) {
free((char *) m);
return (NULL);
}
m->m_size = size;
/*
* Insert at head: change to tail if mem usage is more
* `queueish' than `stackish'.
*/
m->m_next = m_base.m_next;
m->m_prev = &m_base;
m_base.m_next->m_prev = m;
m_base.m_next = m;
return (m->m_mem);
}
/*
* Locate the queue element corresponding to the given memory
* region.
*/
static struct mymem *
myfind(mem)
register char *mem;
{
register struct mymem *m = &m_base;
while ((m = m->m_next) != &m_base)
if (m->m_mem == mem)
return (m);
return (NULL);
}
/*
* Free a region, and drop it from the queue.
*/
myfree(mem)
char *mem;
{
register struct mymem *m = myfind(mem);
if (m == NULL) {
/*
* Complain? Abort? Or what?
* Change to suit local tastes...
*/
(void) fprintf(stderr, "myfree: invalid free\n");
(void) fflush(stderr);
abort();
}
/* remove from queue */
m->m_next->m_prev = m->m_prev;
m->m_prev->m_next = m->m_next;
/* and discard */
free(m->m_mem);
free((char *) m);
}
unsigned
mysize(mem)
char *mem;
{
struct mymem *m;
if ((m = myfind(mem)) == NULL)
return (0); /* not allocated */
return (m->m_size);
}
This definitely *is* portable, if slow for large remembrance queues.
Of course, malloc() knows all along how big the allocated region
is (though the number it knows might be larger than the original
request); so it is a shame to have to go through all this effort.
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516)
UUCP: seismo!umcp-cs!chris
CSNet: chris at umcp-cs ARPA: chris at mimsy.umd.edu
More information about the Comp.lang.c
mailing list