xkfz007
xkfz007

Reputation: 225

What do the memory operations malloc and free exactly do?

Recently I met a memory release problem. First, the blow is the C codes:

#include <stdio.h>
#include <stdlib.h>
int main ()
{
      int *p =(int*) malloc(5*sizeof (int));

      int i ;
      for(i =0;i<5; i++)
           p[i ]=i;
      p[i ]=i;
      for(i =0;i<6; i++)
           printf("[%p]:%d\n" ,p+ i,p [i]);
      free(p );
      printf("The memory has been released.\n" );
}

Apparently, there is the memory out of range problem. And when I use the VS2008 compiler, it give the following output and some errors about memory release:

[00453E80]:0
[00453E84]:1
[00453E88]:2
[00453E8C]:3
[00453E90]:4
[00453E94]:5

However when I use the gcc 4.7.3 compiler of cygwin, I get the following output:

[0x80028258]:0
[0x8002825c]:1
[0x80028260]:2
[0x80028264]:3
[0x80028268]:4
[0x8002826c]:51
The memory has been released.

Apparently, the codes run normally, but 5 is not written to the memory. So there are maybe some differences between VS2008 and gcc on handling these problems. Could you guys give me some professional explanation on this? Thanks In Advance.

Upvotes: 0

Views: 193

Answers (3)

mathieu
mathieu

Reputation: 3174

It seems that you have multiple questions, so, let me try to answer them separately:

  1. As pointed out by others above, you write past the end of the array so, once you have done that, you are in "undefined behavior" territory and this means that anything could happen, including printing 5, 6 or 0xdeadbeaf, or blow up your PC.

  2. In the first case (VS2008), free appears to report an error message on standard output. It is not obvious to me what this error message is so it is hard to explain what is going on but you ask later in a comment how VS2008 could know the size of the memory you release. Typically, if you allocate memory and store it in pointer p, a lot of memory allocators (the malloc/free implementation) store at p[-1] the size of the memory allocated. In practice, it is common to also store at address p[p[-1]] a special value (say, 0xdeadbeaf). This "canary" is checked upon free to see if you have written past the end of the array. To summarize, your 5*sizeof(int) array is probably at least 5*sizeof(int) + 2*sizeof(char*) bytes long and the memory allocator used by code compiled with VS2008 has quite a few checks builtin.

  3. In the case of gcc, I find it surprising that you get 51 printed. If you wanted to investigate wwhy that is exactly, I would recommend getting an asm dump of the generated code as well as running this under a debugger to check if 5 is actually really written past the end of the array (gcc could well have decided not to generate that code because it is "undefined") and if it is, to put a watchpoint on that memory location to see who overrides it, when, and why.

Upvotes: 0

AnT stands with Russia
AnT stands with Russia

Reputation: 320361

There's no deterministic "explanation on this". Writing data into the uncharted territory past the allocated memory limit causes undefined behavior. The behavior is unpredictable. That's all there is to it.

It is still strange though to see that 51 printed there. Typically GCC will also print 5 but fail with memory corruption message at free. How you managed to make this code print 51 is not exactly clear. I strongly suspect that the code you posted is not he code you ran.

Upvotes: 1

zen
zen

Reputation: 357

This is normal as you have never allocated any data into the mem space of p[5]. The program will just print what ever data was stored in that space.

Upvotes: 1

Related Questions