how can i know the allocated memory size of pointer variable in c

40,201

Solution 1

You could also implement a wrapper for malloc and free to add tags (like allocated size and other meta information) before the pointer returned by malloc. This is in fact the method that a c++ compiler tags objects with references to virtual classes. Here is one working example:

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

void * my_malloc(size_t s) 
{
  size_t * ret = malloc(sizeof(size_t) + s);
  *ret = s;
  return &ret[1];
}

void my_free(void * ptr) 
{
  free( (size_t*)ptr - 1);
}

size_t allocated_size(void * ptr) 
{
  return ((size_t*)ptr)[-1];
}

int main(int argc, const char ** argv) {
  int * array = my_malloc(sizeof(int) * 3);
  printf("%u\n", allocated_size(array));
  my_free(array);
  return 0;
}

The advantage of this method over a structure with size and pointer

 struct pointer
 {
   size_t size;
   void *p;
 }; 

is that you only need to replace the malloc and free calls. All other pointer operations require no refactoring.

Solution 2

Although it may be possible that some libraries allows you to determine the size of an allocated buffer, it wouldn't be a standard C function and you should be looking at your library's own documentations for this.

However, if there are many places that you need to know the size of your allocated memory, the cleanest way you could do it is to keep the size next to the pointer. That is:

struct pointer
{
    size_t size;
    void *p;
};

Then every time you malloc the pointer, you write down the size in the size field also. The problem with this method however is that you have to cast the pointer every time you use it. If you were in C++, I would have suggested using template classes. However, in this case also it's not hard, just create as many structs as the types you have. So for example

struct charPtr
{
    size_t size;
    char *p;
};
struct intPtr
{
    size_t size;
    int *p;
};
struct objectPtr
{
    size_t size;
    struct object *p;
};

Given similar names, once you define the pointer, you don't need extra effort (such as casting) to access the array. An example of usage is:

struct intPtr array;
array.p = malloc(1000 * sizeof *array.p);
array.size = array.p?1000:0;
...
for (i = 0; i < array.size; ++i)
    printf("%s%d", i?" ":"", array.p[i]);
printf("\n");

Solution 3

There is no portable way but for windows:

#include <stdio.h>
#include <malloc.h>

#if defined( _MSC_VER ) || defined( __int64 ) /* for VisualC++ or MinGW/gcc */    
#define howmanybytes(ptr) ((unsigned long)_msize(ptr))
#else
#error no known way
#endif

int main()
{
  char *x=malloc(1234);

  printf( "%lu", howmanybytes(x) );

  return 0;
}

Solution 4

It is impossible to know how much memory was allocated by just the pointer. doing sizeof (p) will get the size of the pointer variable p which it takes at compile time, and which is the size of the pointer. That is, the memory the pointer variable takes to store the pointer variable p. Inside p the starting address of the memory block is stored.

Once you allocate some memory with malloc it will return the starting address of the memory block, but the end of the block cannot be found from it, as there is no terminator for a block. You define the end of the block therefore you need to identify it by any means, so store it somewhere. Therefore you need to preserve the block length somewhere to know where the block which is pointed to by p ends.

Note: Although the memory allocation structure keeps track of allocated and unallocated blocks, therefore we can know the allocated memory block length from these structures, but these structures are not available to be used by the users, unless any library function provides them. Therefore a code using such feature is not portable (pointed by @Rudy Velthuis) . Therefore it is the best to keep track of the structure yourself.

Solution 5

You need to keep track of it in a variable if you want to know it for later:

char *p = NULL;
int sizeofp = 2000*sizeof(char);
p = (char *)malloc(sizeofp);
printf("size of p = %d\n",sizeofp);
Share:
40,201
RoCkStUnNeRs
Author by

RoCkStUnNeRs

Updated on July 05, 2022

Comments

  • RoCkStUnNeRs
    RoCkStUnNeRs almost 2 years

    I have faced some problem in this case can you please your ideas.

    main()
    {
    char *p=NULL;
    p=(char *)malloc(2000 * sizeof(char));
    printf("size of p = %d\n",sizeof (p));
    }
    

    In this program Its print the 4 that (char *) value,but i need how many bytes allocated for that.

  • Stuart Cook
    Stuart Cook over 12 years
    And if you didn't allocate it, there is simply no (standard) way to find out how large the allocation was.
  • Lundin
    Lundin over 12 years
    You should not typecast the result of malloc in C. stackoverflow.com/search?q=typecast+result+malloc
  • Lundin
    Lundin over 12 years
    You should not typecast the result of malloc in C. stackoverflow.com/search?q=typecast+result+malloc
  • Rudy Velthuis
    Rudy Velthuis over 12 years
    While I agree with what you wrote, there is obviously a way, since free() must know the size too. But there is not always a publicly accessible and certainly no portable way.
  • phoxis
    phoxis over 12 years
    yes, free must know, but it is dependent on the internal structure and the algorithm being used. Therefore "it is impossible" is an overstatement.
  • MByD
    MByD over 12 years
    @Lundin - that's true, this is a habit from writing C code in C++ environment
  • Chris Reid
    Chris Reid about 9 years
    Some compilers complain if you do not cast the result of malloc to a pointer type, especially if you are casting to a struct pointer or a typedef custom pseudo type. If you are OCD and cannot stand any feedback warnings from a compiler then you may wish to silence such warnings with a cast.
  • Leslie Godwin
    Leslie Godwin about 8 years
    Good answer. I like it.
  • Alex Byrth
    Alex Byrth about 8 years
    Nice approach! But there are some very special cases where this method is not suitable. I mean when required alignment is != sizeof(size_t). That is the case of SSE data, which uses 128bits alignment, and aligned data to meet cache lines (64bits). The padding of size_t breaks the alignment obtained with _aligned_malloc. But in all other cases where default alignment matches sizeof(size_t) (usually 32 or 64bits) that's perfect.
  • Alex Byrth
    Alex Byrth about 8 years
    Actually, above code breaks the default malloc's 16 bytes alignment in x86_64. The size_t padding cuts the first 8 bytes. An easy solution should be return &ret[2] on allocation; use index -2 in both allocated_size() and my_free() functions.
  • frank17
    frank17 over 7 years
    @MByD your code is correct but your statement is missing an important information. When allocating a block of memory, let's say 50, because of the header (for storing information about the allocated block), the data memory is actually smaller than 50, maybe about 45, because of the header in the structure. If I am wrong please let me know, but I am pretty sure I remember it good.
  • MByD
    MByD over 7 years
    @frank17 - it depends on the level you consider as "allocated". If you call malloc(50) then you will have 50 bytes available for use, and some extra bytes for allocation management by the system.
  • JuMoGar
    JuMoGar about 6 years
    Cool, great idea