Malloc行为解释

时间:2014-01-29 15:51:32

标签: c memory-management malloc

我正在测试malloc以了解它的行为,并且在一些操作后我发现了一些奇怪的东西。

我使用相同的var进行了3次不同的测试。

首先,我已经逐个分配和释放我的3 var:

char  * a = malloc(10 * sizeof(char));
printf("\na = %p\n", a);
free(a);
char  * b = malloc(10 * sizeof(char));
printf("b = %p\n", b);
free(b);
char  * c = malloc(10 * sizeof(char));
printf("c = %p\n\n", c);
free(c);

此显示:

a = 0xd34010
b = 0xd34010
c = 0xd34010

逻辑上,它显示相同的地址,内存空间被回收。

然后,我有malloc我的3 var,然后free:

printf("Alloc 3 times and then free :\n");
a = malloc(10 * sizeof(char));
printf("\na = %p\n", a);
b = malloc(10 * sizeof(char));
printf("b = %p\n", b);
c = malloc(10 * sizeof(char));
printf("c = %p\n\n", c);
free(a); free(b); free(c);

它显示我:

a = 0xd34010
b = 0xd34030
c = 0xd34050

a是合乎逻辑的,因为最后一个c变量已被释放,因此重用了内存空间。 bc的地址也是合乎逻辑的,因为ab不是免费的,因此地址会增加。

现在,它变得非常奇怪。 我malloc a,然后b,释放a,malloc c和free b和c:

printf("Alloc, free, alloc :\n\n");
a = malloc(10 * sizeof(char));
printf("a = %p\n", a);
b = malloc(10 * sizeof(char));
printf("b = %p\n", b);
free(a);
c = malloc(10 * sizeof(char));
printf("c = %p\n", c);
free(b); free(c);

结果是:

a = 0xd34050
b = 0xd34030
c = 0xd34050

我的问题是:为什么a等于0xd34050而不是0xd34010?为什么b的地址低于a的地址?

5 个答案:

答案 0 :(得分:4)

因为这是在您使用的特定环境中实现内存分配的方式。这可能听起来很糟糕,但是有这样的例行程序的全部意义在于他们可以为你处理簿记;你有更重要的事情要做!

答案 1 :(得分:3)

我怀疑你是在一个程序中执行这些测试,而你正在使用的malloc实现维护了一些最近释放的块。

因此,在第一次测试中:

  • 第一个malloc需要新空间,因此给出了0xd34010。
  • 0xd34010已被释放。
  • 通过提供最近释放的块0xd34010来满足第二个malloc
  • 0xd34010已被释放。
  • 通过提供最近释放的块0xd34010来满足第三个malloc
  • 0xd34010已被释放。

然后,在第二次测试中:

  • 通过提供最近释放的块0xd34010来满足第一个malloc
  • 第二个malloc需要新空间,因此给出了0xd34030。
  • 第三个malloc需要新空间,因此给出了0xd34050。
  • 0xd34010已被释放。
  • 0xd34030已被释放。
  • 0xd34050已被释放。

然后,在第三次测试中:

  • 通过提供最近释放的块0xd34050来满足第一个malloc
  • 通过提供最近释放的(并且仍然是免费的)块0xd34030来满足第二个malloc
  • 0xd34050已被释放。
  • 通过提供最近释放的块0xd34050来满足第三个malloc
  • 0xd34030已被释放。
  • 0xd34050已被释放。

当然,C标准无法保证这种行为。这仅仅是您在这个特定实例中发生的事情的潜在解释。

答案 2 :(得分:0)

你知道printf还调用malloc来分配流缓冲区吗?在关闭stdout之前,不一定要清除这些缓冲区。

在打印之前,请尝试单独保存所有指针。

答案 3 :(得分:0)

原因可能是

  

为什么等于0xd34050而不是0xd34010?

你机器中的其他一些进程已占用地址0xd34010,因此编译器会为你提供下一个可用内存。

到目前为止我知道,依赖于编译器,内存可能按升序或降序分配。它不一定是按升序排列的。

答案 4 :(得分:0)

  1. 取决于机器。您的编译器的簿记例程就是这样做的。这可能是由于给予了内存限制。

  2. 由于您使用了malloc,因此它使用堆内存