7

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.

phoxis
  • 60,131
  • 14
  • 81
  • 117
RoCkStUnNeRs
  • 301
  • 1
  • 4
  • 9
  • You (and the answerers) can omit `sizeof(char)` It is by definition always `1`. – glglgl Aug 26 '11 at 08:55
  • You should not typecast the result of malloc in C. http://stackoverflow.com/search?q=typecast+result+malloc – Lundin Aug 26 '11 at 08:57

6 Answers6

11

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.

StefanW
  • 337
  • 2
  • 5
  • Good answer. I like it. – Leslie Godwin Apr 20 '16 at 04:54
  • 2
    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 May 01 '16 at 02:04
  • 2
    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. – Alex Byrth May 01 '16 at 02:41
  • I am a newcomer to C and have custom (aligned) alloc/free routines around a struct before seeing this approach (which I like). Could you expand a little on your last sentence - 'All other pointer operations require no refactoring' - in particular re the refactoring benefit. At the moment, I like the idea, for example, of recasting a typed pointer then +1 to get the allocated size (as opposed to passing around a custom struct pointer)... – Peter Aug 08 '23 at 00:38
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;
}
user411313
  • 3,930
  • 19
  • 16
3

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");
Shahbaz
  • 46,337
  • 19
  • 116
  • 182
2

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.

phoxis
  • 60,131
  • 14
  • 81
  • 117
  • 2
    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. – Rudy Velthuis Aug 26 '11 at 09:00
  • 1
    yes, free must know, but it is dependent on the internal structure and the algorithm being used. Therefore "it is impossible" is an overstatement. – phoxis Aug 26 '11 at 09:02
1

You cannot use the sizeof in this case, since p is a pointer, not an array, but since you allocate it, you already know:

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

Edit - If the malloc fails to allocate the size you wanted, it won't give you a pointer to a smaller buffer, but it will return NULL.

MByD
  • 135,866
  • 28
  • 264
  • 277
  • 1
    And if you *didn't* allocate it, there is simply no (standard) way to find out how large the allocation was. – Stuart Cook Aug 26 '11 at 08:43
  • You should not typecast the result of malloc in C. http://stackoverflow.com/search?q=typecast+result+malloc – Lundin Aug 26 '11 at 08:57
  • @Lundin - that's true, this is a habit from writing C code in C++ environment – MByD Aug 26 '11 at 09:39
  • @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. – frank17 Oct 02 '16 at 10:52
  • @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. – MByD Oct 04 '16 at 18:29
1

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);
Paul
  • 139,544
  • 27
  • 275
  • 264
  • You should not typecast the result of malloc in C. http://stackoverflow.com/search?q=typecast+result+malloc – Lundin Aug 26 '11 at 08:56
  • 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. – Chris Reid Mar 21 '15 at 23:51