Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to find the Memory Allocated to the Pointer, without searching for the malloc statement

Tags:

c

gdb

Suppose I have allocated memory to some pointer in a function foo:

void foo()
{    
    // ...  
    int *ptr = malloc(20*sizeof(int));  

    bar (ptr);
}  

From foo(), I pass this pointer to bar() and let's say from bar() to another function.

Now, at some point of time, I want to check: How much memory was allocated to the pointer.

Is there any possible way, without searching for the statement:

int *ptr = malloc(20*sizeof(int)); 

to figure out how much memory is allocated to the pointer, using GDB?

Thanks.

like image 401
Sandeep Singh Avatar asked Apr 28 '11 02:04

Sandeep Singh


2 Answers

The answer is: it depends.

Many systems provide msize() [1], malloc_usable_size() [2], or similar function. If you are on such a system, (gdb) print malloc_usable_size(ptr) is all you need.

[1] http://msdn.microsoft.com/en-us/library/z2s077bc(v=vs.80).aspx
[2] http://www.slac.stanford.edu/comp/unix/package/rtems/doc/html/libc/libc.info.malloc.html

like image 73
Employed Russian Avatar answered Sep 20 '22 14:09

Employed Russian


In general, no. C doesn't provide a way to get the size of an allocated block of memory. You need to keep track of how much memory you allocated yourself.

BUT, on some C libraries, there is a function to get the usable size of a block of memory - malloc_usable_size (found in <malloc.h> on Linux systems, with no manpage). Note that this does not work on all libcs, and may report a value larger than you requested. Please, use it only for debugging.

For completeness, my original answer, which dives into the low-level heap metadata, prior to @Employed Russian pointing out malloc_usable_size:

BUT, you may be able to extract this manually. Note, however, that this all can vary depending on your OS, CPU architecture, and C library. I will assume you're using eglibc 2.12.1; your results may vary anywhere else.

WARNING: Seriously, DO NOT use this except for debugging in gdb. Really. I mean it.

The glibc memory allocator stores chunks of memory like this (out of a doc comment in malloc/malloc.c):

    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Size of previous chunk, if allocated            | |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Size of chunk, in bytes                       |M|P|
      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             User data starts here...                          .
            .                                                               .
            .             (malloc_usable_size() bytes)                      .
            .                                                               |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Size of chunk                                     |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Your data is at 'mem' here, and the size of chunk includes the header. The P flag indicates whether the previous-chunk data is valid, and M indicates this is a mmap mapping (for large mallocs). All of that isn't too important; what's important is that the size lives one pointer-sized increment before your memory; you just have to mask out those flags and subtract the header size:

Breakpoint 1, main () at test.c:8
8               char *a = malloc(32);
(gdb) n
10              free(a);
(gdb) print (*((unsigned long long*)a - 1) & ~3) - sizeof(unsigned long long)*2
$14 = 32

Caveat: The actually allocated size may be larger than you requested. Don't try to get smart and use the excess. Ask for how much you need at the start.

Caveat 2: This only works with glibc. And it only works with certain versions of glibc. and thus may break at any moment without any warning. I can't stress this enough; DO NOT use this in your actual code; only for debugging when you have exhausted every other option. Your code needs to keep track of its buffer sizes on its own.

like image 25
bdonlan Avatar answered Sep 20 '22 14:09

bdonlan