4

Here is my program:

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

main(){
   char *p1, *p2, *p3, *p4;

   p1 = (char*)malloc(10);
   p2 = (char*)malloc(10);
   p3 = (char*)malloc(16);
   p4 = (char*)malloc(32);

   printf("p1 points at: %d\n", p1);
   printf("p2 points at: %d\n", p2);
   printf("p3 points at: %d\n", p3);
   printf("p4 points at: %d\n\n", p4);

   system("PAUSE");
}

This produces the following output on my PC:

p1 points at: 6492080

p2 points at: 6492104

p3 points at: 6492128

p4 points at: 6492152

So, each memory space that malloc allocates starts 24 bytes further, no matter how many bytes are allocated. Why is that? I appreciate your help!

mgus
  • 808
  • 4
  • 17
  • 39
  • 1
    The compiler should have warned you about, your %d format strings. Pointers are printed using %p. Do you have warnings enabled? Also, don't cast the return from malloc. – William Morris Oct 20 '12 at 15:53

3 Answers3

5

The exact behavior of malloc is determined by your particular implentation (compiler/libc/OS). By printing out the addresses, your program is engaged in undefined behavior.

If you narrowed the scope of your question by telling us what compiler you are using, what OS you are on, what architecture, and what version of libc you are using, then we might be able to give a more specific answer about that implementation and why the number is 24.

My GUESS would be that in your implementation, each malloced region of memory needs to start at an address that is a multiple of 8, and also there are 8 bytes of overhead.

EDIT: If you called malloc again to create p5 after p4, the pattern definitely cannot continue, so your statement of "each memory space that malloc allocates starts 24 bytes further, no matter how many bytes are allocated." is false.

David Grayson
  • 84,103
  • 24
  • 152
  • 189
  • Okay, I'm using Dev-C++ compiler v.4.9.9.2 on a Windows 7 64 bit operating system. Where can I find the libc version? Finally, I understand my mistake on the question, but you get the point! – mgus Oct 22 '12 at 17:21
3

There is no guarantee that an int and some void* or char* pointer have the same size (on my Debian/Linux/AMD64 system, int-s are 32 bits but pointers are 64 bits). You might want to include <stdint.h> and use intptr_t.

The implementation of malloc may sometimes reserve a few bytes before the allocated zone for housekeeping purposes. And malloc shoud always return an enough aligned pointer (alignment constraints are compiler, runtime, and processor specific). There is absolutely no guarantee that malloc returns an increasing sequence of results in time (especially in real programs, where millions of calls to malloc are mixed with millions of calls to free; you may even have some memory fragmentation in such long running processes).

And I am quite sure that if you add a p5 = malloc(10120); after your p4 you won't see a 24 bytes distance between p5 and p4, since when it is successful malloc guarantee that its result is not an alias of any previous result, so that p5 should have at least a distance of 32 bytes with p4 (which contains a 32 bytes chunk).

Almost always, the standard C library implements malloc above some lower-level primitive, usually some syscall to fetch consecutive virtual memory pages. On Linux, these syscalls are often mmap(2) (perhaps with sbrk(2)) and since Linux systems are mostly free software you could actually study and improve the implementation of malloc e.g. Musl Libc implementation of malloc (the more common GNU libc malloc implementation is perhaps more complex to understand). So you could learn more by switching to Linux.

An implementation of malloc could in theory always fail. In practice, malloc may succeed, but you should always test for the failure case.

Of course, most implementations care about free and re-use recently free-d memory zone (without any syscalls), if possible, in their malloc implementation. How to organize the heap to be able make malloc and free efficient is difficult (and may be still a research subject, if you want it to be very good).

You might want to read the wikipedia page on malloc.

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
1

malloc shall allocate space for an object of size size. Nothing prevents your implementation to add padding bytes for alignment purpose, for instance. Another example: some memory management implementations keep the size of your block before the allocated space.

If you want more details, you should precise your implementation.

md5
  • 23,373
  • 3
  • 44
  • 93