The size of the memory block is typically stored just below the pointer. While this is a hack (you said I could...), the following code runs on my Linux box:
#include <stdio.h>
#include <stdlib.h>
int main(){
int *p, n=123;
p = (int*)malloc(n*sizeof(int));
printf("allocated %d bytes for p\n", n*sizeof(int));
printf("p[-2] : %d \n", *(p-2));
printf("malloc_useable_size(p) : %d\n", malloc_usable_size(p));
free(p);
}
The output it produces is this:
allocated 492 bytes to p
p[-2] : 513
malloc_useable_size(p): 504
Note that the size in p[-2] isn't exactly 492
- there is some additional space used up due to housekeeping and boundary alignment etc.
Also note - this worked with the gcc
compiler; but g++
complained about pointer conversion, and that I hadn't declared malloc_useable_size()
. I added that line out of curiosity after seeing @fanl's answer. I also played around a bit with the output of mallinfo
after seeing the answer of @OliCharlesworth.
You can change the value of n, and you will see that things agree very nicely - for example, if you step n (in my above code) from 100 to 119, the values of the different variables of interest are as follows:
n | p[-2] | usable | uordblks
----+-------+--------+---------
100 417 408 416
101 417 408 416
102 417 408 416
103 433 424 432
104 433 424 432
105 433 424 432
106 433 424 432
107 449 440 448
108 449 440 448
109 449 440 448
110 449 440 448
111 465 456 464
112 465 456 464
113 465 456 464
114 465 456 464
115 481 472 480
116 481 472 480
117 481 472 480
118 481 472 480
119 497 488 496
There's always a difference of 9 between usable
and p[-2]
, and of 1
between p[-2]
and uordblks
. The advantage of the p[-2]
method is that it tells you exactly what you asked for - the size of this pointer. The other calls may actually tell you what you really wanted...
PS It's quite possible that for very large blocks of memory, you need to look at the long integer
that lives at *((long int*)(p)-1)
. That gives me the inspiration for a nice macro:
#define PSIZE(a) (*((long int*)(a)-1))
Then you can find out the size of any pointer with
printf("my pointer size is %ld\n", PSIZE(myPointer));
Without having to worry about the type of the pointer. I confirmed that this works for different types of pointer, and for blocks > 4G. Obviously you can decide to subtract 1 in the macro so the number agrees exactly with mallinfo().
EDIT: a more complete description of what is stored just below the pointer is given in one of the answers to this earlier question. This shows that the "+1" I observed is actually due to a flag that is stored in the LSB. The correct approach is to AND the result with ~3, to clear the two LSBs, then subtract the size of the (long int*) from the result (actually the original answer subtracts 2*sizeof(unsigned long int) but I think that's wrong):
#define PSIZE(a) ((*((long int*)(a)-1))&~3 - sizeof(long int*))
The linked answer STRONGLY recommends to use this for debug only, and not to rely on it for actual code. I feel compelled to repeat that warning.