【问题标题】:What do the memory operations malloc and free exactly do?内存操作 malloc 和 free 究竟做了什么?
【发布时间】:2013-11-22 02:02:10
【问题描述】:

最近遇到内存释放问题。首先,打击是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在处理这些问题上可能存在一些差异。 各位大神能不能给个专业的解释?提前致谢。

【问题讨论】:

  • 您为 5 个项目分配了空间,但索引超出了分配量的末尾。这是未定义的行为,任何事情都可能发生。
  • 您的第二个 for 循环超出了分配的范围。 p[5] 就是当时内存中的任何值。
  • 糟糕,我没有看到多余的 p[i] = i,这意味着最后一个值应该是 5。不确定 gcc 在那里做了什么。

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


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    没有确定性的“对此的解释”。超过分配的内存限制将数据写入未知领域会导致未定义的行为。行为是不可预测的。仅此而已。

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

    【讨论】:

    • 这里的代码正是我运行的。我知道索引超出范围。我想知道为什么代码会免费崩溃。 free怎么知道要释放的内存大小是多少?
    • malloc 保存在特定地址分配的内存量,因此free 可以释放相同的量。 malloc 如何保存该值以及对分配块周围的任何损坏检查都是特定于实现的。
    • 我的同事给了我一些解释,VS2008会检查内存中的值是否有效来决定它要释放的内存大小。
    【解决方案3】:

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

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

    2. 对于 gcc,我发现打印出 51 令人惊讶。如果你想调查为什么会这样,我建议获取生成代码的 asm 转储,并在调试器下运行它以检查 5 是否真的写在数组的末尾(gcc 很可能决定不生成该代码,因为它是“未定义的”),如果是,则在该内存位置放置一个观察点,以查看谁覆盖它、何时以及为什么覆盖它。

    【讨论】:

    • 感谢您的详细回复。我更了解内存分配。
    猜你喜欢
    • 2011-07-23
    • 2012-07-23
    • 2016-09-10
    • 2023-03-15
    • 2012-10-17
    • 2021-06-04
    • 1970-01-01
    • 2018-07-30
    • 2019-10-06
    相关资源
    最近更新 更多