malloc和free的内存操作究竟做了什么?

时间:2013-11-22 02:02:10

标签: c++ c visual-studio-2008 gcc

最近我遇到了内存释放问题。首先,打击是C代码:

#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" );
}

显然,存在超出范围的内存问题。当我使用VS2008编译器时,它会提供以下输出和一些有关内存释放的错误:

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

但是当我使用cygwin的gcc 4.7.3编译器时,我得到以下输出:

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

显然,代码运行正常,但5不会写入内存。 因此,在处理这些问题时,VS2008和gcc之间可能存在一些差异。 你们能给我一些专业的解释吗?在此先感谢。

3 个答案:

答案 0 :(得分:1)

对此没有确定性的“解释”。将数据写入超出分配的内存限制的未知区域会导致未定义的行为。这种行为是不可预测的。这就是它的全部内容。

虽然看到那里印有51但仍然很奇怪。通常,GCC也会打印5但在free处失败并显示内存损坏消息。您如何设法使此代码打印51并不十分清楚。我强烈怀疑你发布的代码不是你运行的代码。

答案 1 :(得分:1)

这是正常的,因为您从未将任何数据分配到p [5]的mem空间中。该程序将只打印存储在该空间中的数据。

答案 2 :(得分:0)

您似乎有多个问题,所以,让我尝试分别回答:

  1. 正如上面其他人所指出的,你写过数组的末尾,所以,一旦你这样做,你就处于“未定义的行为”领域,这意味着任何事情都可能发生,包括打印5,6或0xdeadbeaf,或炸毁你的电脑。

  2. 在第一种情况下(VS2008),free似乎在标准输出上报告错误消息。我不明白这个错误信息是什么,所以很难解释发生了什么,但你稍后会在评论中询问VS2008如何知道你发布的内存的大小。通常,如果分配内存并将其存储在指针p中,则许多内存分配器(malloc / free实现)以p [-1]存储分配的内存大小。在实践中,通常还在地址p [p [-1]]处存储特殊值(例如,0xdeadbeaf)。免费检查这个“金丝雀”,看看你是否已经写过数组的末尾。总而言之,你的5 * sizeof(int)数组可能至少有5 * sizeof(int)+ 2 * sizeof(char *)个字节长,并且用VS2008编译的代码使用的内存分配器内置了相当多的检查。

  3. 在gcc的情况下,我发现你打印51页令人惊讶。如果你想要正确地研究wwhy,我建议获取生成代码的asm转储以及在调试器下运行它以检查5是否实际上是在数组末尾写入的(gcc很可能已经决定不生成该代码,因为它是“未定义的”),如果是,则在该内存位置放置一个观察点,以查看谁覆盖它,何时以及为什么。