views:

1002

answers:

10

I have this piece of code

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

int main(){
void *a, *b;

a=malloc(16);
b=malloc(16);
printf("\n   block size (for a): %p-%p : %li",b,a,b-a);

a=malloc(1024);
b=malloc(1024);
printf("\n   block size (for a): %p-%p : %li",b,a,b-a); 
}

This shouldn't display the the last allocated block size? (16 or 1024). It prints 24 & 1032, so it has 8 extra bytes...

My problem is (before making this testcase) that i do malloc in a function (1024 bytes), and return the allocated result. When checking the block size on the function return i get 516 blocks... and i dont get it why. I guess this might be the reason for the memory curruption that occurs after doing some processing on the allocated buffers:)

Edit: i've seen http://stackoverflow.com/questions/232691/array-size-from-pointer-in-c and seems to ask the same thing, sorry for reposting.

I've redone my example to my more specific code:

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

short int * mallocStuff(long int number, short int base){
 short int *array;
 int size=1024;

 array=(short int*)calloc(1,size);
 //array=(short int*)malloc(size);

 return array;
}

int main(){
 short int **translatedArray;

 translatedArray=malloc(4*sizeof(short int));

 int i;
 for(i=0;i<4;i++){
  translatedArray[i]=mallocStuff(0,0);

  if(i>0)
   printf("\n   block size (for a): %p-%p : %i",translatedArray[i],translatedArray[i-1],translatedArray[i]-translatedArray[i-1]);
 }

 return 0;
}

And the output is block size (for a): 0x804a420-0x804a018 : 516 block size (for a): 0x804a828-0x804a420 : 516 block size (for a): 0x804ac30-0x804a828 : 516

According to the above post that be bigger than 1024...am i wrong?

A: 

Before the pointer stands the size of the following array, which is a 32/64 bit integer (dont know if signed or unsigned)

Ronny
+9  A: 

The malloc function always allocates slightly more than you ask for, in order to store some bookkeeping information. After all, when you call free() it needs to know how big the block is.

Also, generally malloc implementations will round the requested size up to the next multiple of 8 or 16 or some other round-ish number.

Update: The real answer to your question lies in your use of the short int type. When doing pointer arithmetic (subtraction) between typed pointers, C and C++ return the difference in the number of things pointed to. Since you are pointing to short int, which is two bytes in size, the value returned is half of what you are expecting.

On the other hand, malloc always allocates a given number of bytes, no matter what you cast the result to afterward. Try this:

    array=(short int*)malloc(sizeof(short int) * size);
Greg Hewgill
+2  A: 

malloc() will have it's own overhead.

Not to mention that there's no guarantee that 2 consecutive allocations will be next to each other to begin with.

Michael Burr
+22  A: 

First, Malloc makes no guarantees that two successive malloc calls return successive pointers.

Second, depending on your specific architecture, different alignment rules apply; sometimes you might ask for a single byte, but the architecture prefers allocations on 8- or 4-byte intervals.

Third, malloc needs some overhead to store how big the allocated block is, etc.

Don't make assumptions about what malloc is doing past what the documentation says!

SquareCog
assumptions will get you in trouble with most anything sooner or later
BCS
+1  A: 

If malloc returns anything other than null, then the memory that it has been allocated for your program has the size that you passed to malloc. Taking the pointer difference between the return values of two difference calls to malloc could have any value and has nothing (well little) to do with the block size of the first allocated block.

Charles Bailey
+11  A: 

There are no guarantees that two malloc calls return blocks exactly packed together - in fact there aren't any guarantees about the result at all, except that if it's non NULL it will point to a block as least as big as the one requested.

Internally, most mallocs hold working data to help them manage the heap. For instance, those 8 bytes might contain two pointers - one pointing to the next block, and one pointing to the previous block. I don't know what those 8 bytes are because you didn't mention which OS you're running on, but it's perfectly normal for malloc to use some memory for itself behind the scenes.

Some allocators (eg on windows) provide a library function to discover block size given a pointer, however, some don't, as it's a rather esoteric feature.

Mike Hearn
Alignment is also guaranteed to some extent, if I remember correctly.
Arkadiy
And you're guaranteed to get *at least* as much as you ask for if the call succeeds.
Max Lybbert
As likely to be a size and a pointer to the next or previous block.
Jonathan Leffler
+2  A: 

What malloc returns depends on the implementation of malloc, and the architecture. As others have already said, you are guaranteed to get at LEAST the requested amount of memory, or NULL. This is also why sometimes, you can write past the end of an array, and not get a segmentation fault. It's because you actually DO have valid access to this memory, you just didn't know it.

Mongoose
+2  A: 

malloc() is usually implemented by splitting the available heap in chunks of various sizes. In your case, malloc() returns 2 consecutive 1024 (or 16) byte chunks. The 8 byte space you mention is used by malloc() for bookkeeping information.

See Doug Lea's malloc() impl notes here to understand what is going in behind the scenes: http://g.oswego.edu/dl/html/malloc.html

Georgios Gousios
+3  A: 

You have a bug. Instead of:

translatedArray=malloc(4*sizeof(short int));

You should have

translatedArray=malloc(4*sizeof(short int*));

Note the missing pointer in your code. I suspect this is where your observed behavior stems from.


Also notice that 0x804a420 - 0x804a018 = 1032, not 516. The formula translatedArray[i] - translatedArray[i - 1] gives you the number of elements (short ints, or more simply, shorts) in between the two addresses, not the number of bytes.

P Daddy
no, i get the same block sizes.. but i do think you are right about the missing '*'
Quamis
hah, you are wright about the 1032 number... damn
Quamis
A: 

I found this..and check for the link below for more info.

Allocation

A block is allocated from the free pool by first converting the requested bytes to an index in the bucket array, using the following equation:

needed = requested + 8

If needed <= 16, then bucket = 0

If needed > 16, then bucket = (log(needed)/log(2) rounded down to the nearest integer) - 3

The size of each block in the list anchored by the bucket is block size = 2 bucket + 4. If the list in the bucket is null, memory is allocated using the sbrk subroutine to add blocks to the list. If the block size is less than a page, then a page is allocated using the sbrk subroutine, and the number of blocks arrived at by dividing the block size into the page size are added to the list. If the block size is equal to or greater than a page, needed memory is allocated using the sbrk subroutine, and a single block is added to the free list for the bucket. If the free list is not empty, the block at the head of the list is returned to the caller. The next block on the list then becomes the new head.

http://publib.boulder.ibm.com/infocenter/systems/index.jsp?topic=/com.ibm.aix.genprogc/doc/genprogc/sys_mem_alloc.htm

Note that the link is for AIX which may use an entirely different malloc than the glibc on Linux. In fact, klibc, ulibc and any other libc may use different methods. Most libc's also let software override the default malloc.
Zan Lynx