views:

130

answers:

3

I realize that any such function is likely to be non standard, but that's ok for my use case. Basically, I need a method (even if it's only exposed through glibc's syscall() interface) that I can pass a pointer to (a pointer that was returned by a previous call to malloc()) that returns the size of the block the pointer points at. Does such a thing exist?

+1  A: 

So far as I know, there is no such function at least in C90/C99. Some systems, mostly libc, provide functions to get allocated size (e.g. malloc_size() in Mac OS X), but this is not portable and probably you should avoid using that at best.

A: 

There is no need to use non-standard functions, it is not hard to write your own allocator with the necessary functionality.

You have to know the size when you allocate the block, so simply retain that information. There are few situations IMO when you would not know that information, since by definition you knew it when it was allocated. However if you need such functionality, you can do that simply by wrapping malloc(), and pre-pending the size to the block.

void* smalloc( size_t size )
{
    // allocate block with additional space for size
    void* blk = malloc( size + sizeof(size_t) ) ;

    // set the size
    *((size_t*)blk) = size ;

    // return pointer to block after size field (user block)
    return ((size_t*)blk) + 1 ;
}

void sfree( const void* blk )
{ 
    // Free from the size field address, not the user block
    free( ((const size_t*)blk) - 1 ) ;
}

size_t ssize( const void* blk )
{
    // Size is immediately before user block
    return *(((size_t*)blk) - 1) ;
}


On Jim Buck's point; On some target's, some jiggering may be needed to preserve necessary alignment. Some targets will generate less efficient code if alignment is not optimal, others will cause an abort. So beware of this solution. Personally I am wary of teh need for this solution!

One solution perhaps would be to use a data structure such as a hash table with the malloc address as the key, and the size as the content, and using the same wrapper technique store the size separately from the block - at the expense or performance, additional storage, and perhaps some finite limit on capacity in terms of number of blocks that can be managed.

However you do it, the fundamental point remains valid - wrap the basic service to provide what you need.

Clifford
I note that this is more-or-less identical to Emil H's solution given in the second link in dmckee's comment to the original question. However as commented code perhaps it still has merit, so I let it stand.
Clifford
This breaks any alignment guarantees that malloc might otherwise give you on a particular platform. If, for example, you are on a platform that guarantees 8-byte alignment, this code example now turns it into 4-byte alignment.
Jim Buck
(The above assumes a 4-byte sizeof(size_t), of course.)
Jim Buck
Agreed. Additional note added on that issue.
Clifford
A: 

_msize on Windows platforms.

Jim Buck