Rafal
Rafal

Reputation: 1150

How to get the size of the memory allocated dynamically?

Allocating memory dynamically using malloc will return the address from where the memory is allocated. Before that address meta-data is stored; it's a struct.

struct malloc_chunk {  
    int      prev_size;
    int      size;           // size of memory allocated
    struct malloc_chunk* fd;
    struct malloc_chunk* bk;
    struct malloc_chunk* fd_nextsize;
    struct malloc_chunk* bk_nextsize;
};

I want to print value of size without using malloc_usable_size(). I tried but I am getting a segfault. I am working on 64-bit Ubuntu.

Upvotes: 0

Views: 2899

Answers (5)

Jonathan Leffler
Jonathan Leffler

Reputation: 753695

Consider the following test code (which has no error checking):

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    void *v1 = malloc(160);
    void *v2 = malloc(160);
    void *v3 = malloc(160);

    printf("v1 = %p\n", v1);
    printf("v2 = %p\n", v2);
    printf("v3 = %p\n", v3);

    ptrdiff_t d1 = v2 - v1;
    ptrdiff_t d2 = v3 - v2;

    printf("d1 = %td\n", d1);
    printf("d2 = %td\n", d2);
    return 0;
}

When compiled on 64-bit Ubuntu 14.04 LTS, the output I got was:

v1 = 0x742010
v2 = 0x7420c0
v3 = 0x742170
d1 = 176
d2 = 176

Since the gap between the returned blocks is 176 bytes and the size allocated is 160 bytes, there are just 16 bytes of overhead. The struct malloc_chunk outlined in the question occupies 40 bytes on a 64-bit platform (24 on a 32-bit platform). It does not fit into the space between allocated chunks of memory.

Therefore, any attempt to access a struct malloc_chunk from a regular block of allocated memory is doomed to failure.

You will have to obtain the source to malloc() to find out how it uses that structure. If I had to guess, it uses it in a separate area altogether. Maybe some of the 16 bytes of overhead tells malloc() where to find the struct malloc_chunk. But that's a guess; I've not looked.

Upvotes: 3

harper
harper

Reputation: 13690

The structure is implementation dependent. You should not use the information at all since it might change at the next compiler or even at the next compiler version.

You should manage the size of memory in user defined structures.

Edit: Memory allocation algorithms usually work with some alignments to

  • avoid unaligned addresses in further allocations
  • provide best performance on architectures where unaligned access is allowed but could result in performance penalties
  • reduce the heap fragmentation be using chunks that are a multiple of a base, e.g. 16 bytes.

Therefore malloc doesn't need to allocate exactly the size that you passed as parameter. It can allocate a chunk the is sufficient to hold the requested size but probably more. It's not necessary for mallocto store the original value, only the chunk size is necessary to free the chunk.

Therefore it's probably impossible to retrieve the size parameter passed in the malloc function call.

Upvotes: 4

VolAnd
VolAnd

Reputation: 6407

First of all malloc_usable_size is Linux/Unix specific function and will not work on Windows, for example.

So, the best way is to save size when allocating memory: just remember how much memory was allocated and than use that value.

Upvotes: 2

Luis Colorado
Luis Colorado

Reputation: 12668

Malloc library normally maintains a list of struct malloc_chunk internally to manage the amounts of memory given to the user up to this point. Normally, to cope with that they have a way to map the returned pointer from malloc(3) to the address of this structure (so free(3) can get to it), but you don't know that mapping for sure.

Normally, they alloc internally the amount to store the memory they give to you and this struct malloc_chunk together, and the struct is aligned in a way that they can get the structure address from the pointer you pass to free(3).

The normal way to cope with this is: The malloc(3) function gives you (void *)(ref + 1), where ref is a struct malloc_chunk * pointer (so it's aligned to the end of this structure) and you have to do just the opposite to get a valid pointer to that structure, that is: ((struct malloc_chunk *)ptr - 1) (convert the pointer to a struct malloc_chunk * pointer, and then go back one structure size to point there)

This expression is of type pointer to struct malloc_chunk, so you can reference its fields with the following code:

void *p = malloc(120);
struct malloc_chunk *mc = (struct malloc_chunk *)p - 1;

printf("prev_size:   %d\n"
       "size:        %d\n"
       "fb:          %p\n"
       "bk:          %p\n"
       "fw_nextsize: %p\n"
       "bk_nextsize: %p\n",
       mc->prev_size,
       mc->size,
       mc->fb,
       mc->bk,
       mc->fw_nextsize,
       mc->bk_nextsize);

I have not been able to test this code, as my <malloc.h> implementation doesn't have this struct malloc_chunk type defined anywhere (or I have not been able to find it). You have to provide a reference of where do you have acquired this type if you want me to be able to reproduce your environment. I'm using gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)

Upvotes: 1

Billy ONeal
Billy ONeal

Reputation: 106539

In the general case, the exact mechanism malloc uses to store the size -- if it even has a mechanism -- is going to be implementation defined. You need to keep track of the size yourself if you need it for anything specific.

Upvotes: 3

Related Questions