可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
So in most implementations malloc stores an header before the allocated memory to keep track of the allocated memory size (so that it can do free and recalloc). What are the header contents?
I wrote a naive code to find it but it doesn't make any sense
int * ptr;
ptr = malloc(12*sizeof(int));
printf("Header = %d\n",*(ptr-1));
It returns
Header = 57
What is happening here?
回答1:
I'm guessing you want to learn and see how the memory is allocated. I would ignore the Undefined Behaviour answers. They are right (of course) when you talk about portability and such, but that is not your question. I think it is a really good idea to try and figure out how the allocation is done.
First I would encourage you to start looking at the malloc implementation for your platform. If that code is not available, you are out of luck and the only think you can do is google for clues how the allocation is done.
If you run linux, you can look at the malloc implementation of glibc or uclibc. Here a link to the uclibc implementation:
http://git.uclibc.org/uClibc/tree/libc/stdlib/malloc/malloc.c
The code has lot of comments, but can be overwhelming.
For your question, look at http://git.uclibc.org/uClibc/tree/libc/stdlib/malloc/malloc.h on line 104.
which is the part you are talking about. You see the layout depends on MALLOC_HEADER_SIZE which can be different for different systems. By reading the code you can learn which types to use, and on which offset the memory size is stored (in this specific implementation)
Of course, above is just an example implementation from uclibc to get you started...
回答2:
Nobody really answered where the number "57" came from, so here's my understanding of it.
The header that is set when using malloc or calloc, at least on the architectures that I've used, is the total size of chunk of memory on the runtime heap, plus a few "boolean flags".
You requested 12 ints, with each int (presumably) being 4 byte. 12x4 = 48. Another 4 byte, for the header block itself (the number 57), is added to this count, leaving us at 52.
So why are you getting 57?
Well, Malloc and Calloc only request memory in 8-bit chunks, to avoid bus errors. The next higher multiple of 8 is 56.
Now, recall that any number that is divisible by 8 has a binary representation that will always end in three 0's. Being the memory-conserving language that C is, compilers take advantage of this fact and use the last three 0's as boolean flags.
In this specific case, the last boolean flag is set, adding 1 to 56, resulting in the number 57 when read as an int.
回答3:
None of this is any of your business (it's an implementation detail, opaque to the user), and what you do is undefined behaviour.
That's as far as the standard goes.
Now, if you want to be naughty and poke around memory, beware that pointer arithmetic operates in units of the type size (e.g. 4 for int
). So you should always cast your pointers to char*
(or an unsigned version) for such shenanigans:
struct Foo * f = malloc(sizeof(Foo) * 7);
const unsigned char * const i_know_what_im_doing = f;
printf("%02X\n", *(i_know_what_im_doing - 1));
回答4:
You are causing Undefined Behavior.
Trying to read beyond the bounds of allocated memory is an UB.
I believe what you are trying to find out is an implementation detail for compilers and will vary from compiler to compiler.
回答5:
This is undefined behaviour. But to be perfectly honest, if you're willing to scratch around in the internals of malloc, the first thing you need to do is actually determine what your malloc is doing.
Once you've determined this, then you can do something more intelligent than just randomly accessing memory outside of the bounds of what you allocated (which is the problem here).
回答6:
With your code you read an int before, and nothing tells you the header is that long.
Moreover, it is implementation specific, so you can never rely on it!
Moreover, trying to access a memory you didn't allocated yourself is an Undefined Behavior!!
I don't know why you want to access it, but it is better not to do anything with that!
If you want more information, on most modern computer the memory in segmented and paginated, and the maximum allocation you can do at one time is of the size the memory segment.
So your header must be able to contain at least that size.
But has you can malloc more than the segment size, they could be additional information stored in this header, you can never now!