9

gcc 4.4.1 c89

I have the following code snippet:

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

 char *buffer = malloc(10240);
 /* Check for memory error */
 if(!buffer)
 {
    fprintf(stderr, "Memory error\n");
    return 1;
 }
 printf("sizeof(buffer) [ %d ]\n", sizeof(buffer));

However, the sizeof(buffer) always prints 4. I know that a char* is only 4 bytes. However, I have allocated the memory for 10kb. So shouldn't the size be 10240? I am wondering am I thinking right here?

Many thanks for any suggestions,

ant2009
  • 27,094
  • 154
  • 411
  • 609
  • 2
    For the most part the C compiler (for any version) doesn't have any idea what the function `malloc` actually does or is used for. All it knows is that it takes an unsigned integer (size_t) and returns a void pointer. It could use it's parameter to seed the random number generator and cast a random number to a `(void *)` for all the compiler cares, so the compiler can't know what the sizeof the memory pointed to is. – nategoose Apr 28 '10 at 17:19

5 Answers5

18

You are asking for the size of a char* which is 4 indeed, not the size of the buffer. The sizeof operator can not return the size of a dynamically allocated buffer, only the size of static types and structs known at compile time.

Péter Török
  • 114,404
  • 31
  • 268
  • 329
  • 2
    `sizeof` can return the size of a dynamic buffer for variable length arrays in C99. – Carl Norum Apr 28 '10 at 16:59
  • Is there any method under c89 that you can find how much memory has been allocated with a dynamically allocated buffer? Thanks. – ant2009 Apr 28 '10 at 17:01
  • 3
    @Carl - VLA's aren't dynamic. They're "variable length" in that their length can be computed at runtime, but not "variable length" in that their length can change. They're still stack-based arrays, which is why `sizeof` is defined to work for them. – Chris Lutz Apr 28 '10 at 17:02
  • 3
    @robUK - Keep track of it yourself using a `struct { char *buf; size_t len; };`. Or use someone else's string library. Or maintain strict adherence to the "always pass lengths with buffers" rule (which you should probably do anyway). – Chris Lutz Apr 28 '10 at 17:04
  • @Carl. I have just tested your concept. I compiled with c99 i.e. -std=c99. However, sizeof still gave me the value 4. – ant2009 Apr 28 '10 at 17:04
  • @robUK - He means for C99 VLAs, i.e. `char c[/*runtime calc*/];` not dynamically allocated arrays, i.e. `char *c = malloc(/*runtime calc*/);`. And C99 VLAs are problematic and only spottily implemented and overall best avoided in my opinion. – Chris Lutz Apr 28 '10 at 17:08
  • @Chris, that's correct, and I agree with the recommendation to not use them. – Carl Norum Apr 28 '10 at 17:50
  • 1
    @robUK, there is no way to know how much memory `malloc()` actually gave you without other OS/library features that might be able to tell you. Those will be operating system/compiler dependent. – Carl Norum Apr 28 '10 at 17:51
  • I hope this is the last incarnation of this question. Its been asked numerous times before. – Tim Post Apr 28 '10 at 19:45
  • 1
    C99 VLAs are the most appropriate choice in many situations, and using them is far better than using the old nonstandard `alloca()`. If no-one uses them, the support will never improve. – caf Apr 29 '10 at 00:23
9

sizeof doesn't work on dynamic allocations (with some exceptions in C99). Your use of sizeof here is just giving you the size of the pointer. This code will give you the result you want:

char buffer[10240];
printf("sizeof(buffer) [ %d ]\n", sizeof(buffer));

If malloc() succeeds, the memory pointed to is at least as big as you asked for, so there's no reason to care about the actual size it allocated.

Also, you've allocated 10 kB, not 1 kB.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
  • This code is more than a little dangerous: it's allocating the buffer on the stack, not the heap. If you let any pointers to this buffer leak out of the function that declares it, you're on the way to stack corruption (and depending on how long your program runs, heap corruption and/or a segmentation fault). – Anon Apr 28 '10 at 17:01
  • 2
    @Anon - It's not dangerous, it just solves the problem a different way. The OP had no requirements about passing the buffer back from a function. – Chris Lutz Apr 28 '10 at 17:10
  • And what, exactly, is the OP's problem? Seems to me that it's keeping track of the size of a heap-allocated structure. Suggesting that the OP use a stack-allocated structure is not a solution to that problem. – Anon Apr 28 '10 at 17:17
3

It is up to you to track the size of the memory if you need it. The memory returned by malloc is only a pointer to "uninitialized" data. The sizeof operator is only working on the buffer variable.

Mark Wilkins
  • 40,729
  • 5
  • 57
  • 110
  • Surely the runtime environment knows the size of the allocated buffer (because `free(void*)` doesn't ask for the size), so why should we have to keep track of it ourselves? – Dai Aug 23 '16 at 22:33
  • The underlying memory management code almost certainly has the size unless it has some magical algorithm for freeing that doesn't require size. But that information is not exposed. – Mark Wilkins Aug 24 '16 at 02:03
  • Is there a reason that data isn't exposed? – Dai Aug 24 '16 at 02:07
  • It wasn't defined that way. [This answer](http://stackoverflow.com/questions/4959938/why-isnt-there-a-memsize-in-c-which-returns-the-size-of-a-memory-block-alloca) discusses it. – Mark Wilkins Aug 24 '16 at 02:23
3

No. buffer is a char *. It is a pointer to char data. The pointer only takes up 4 bytes (on your system).

It points to 10240 bytes of data (which, by the way, is not 1Kb. More like 10Kb), but the pointer doesn't know that. Consider:

int a1[3] = {0, 1, 2};
int a2[5] = {0, 1, 2, 3, 4};

int *p = a1;
// sizeof a1 == 12 (3 * sizeof(int))
// but sizeof p == 4
p = a2
// sizeof a2 == 20
// sizeof p still == 4

It's the main difference between arrays and pointers. If it didn't work that way, sizeof p would change in the above code, which doesn't make sense for a compile-time constant.

Chris Lutz
  • 73,191
  • 16
  • 130
  • 183
2

Replace your sizeof by malloc_usable_size (the manpage indicates that this is non-portable, so may not be available with your particular C implementation).

Anon
  • 126
  • 1
  • 1
    `malloc_usable_size()` is very non-portable. I don't have it on OS X Leopard. Anyway, reliance on it is a terrible idea in the first place (as also stated in the manpage). – Chris Lutz Apr 28 '10 at 17:06
  • NOTE: if you don't care about portability and are on OSX (or someone else didn't care and you are stuck with porting to OSX) malloc_size from is your man for the job. – Stripes Aug 11 '14 at 15:18