2014-12-13 53 views
3

我有点担心posix_memalign()和malloc()在我的系统上的行为。我有以下的测试代码:posix_memalign/malloc在第一次免费拨打电话后分配较低地址

#include <stdio.h> 
#include <stdlib.h> 
#include <assert.h> 

int 
main() 
{ 
    int i; 
    float *data; 
    for (i = 0; i < 5; i++) { 
    assert(!posix_memalign((void**) &data, 16, 100000 * sizeof(float))); 
    printf("data = %p\n", data); 
    } 
    free(data); 
    for (i = 0; i < 5; i++) { 
    assert(!posix_memalign((void**) &data, 16, 100000 * sizeof(float))); 
    printf("data = %p\n", data); 
    } 
    return 0; 
} 

在第一5次分配,posix_memalign()返回高电平地址。后我调用free(),它突然切换到低地址:

% ./aligned 
data = 0x7f74f9974010 
data = 0x7f74f9912010 
data = 0x7f74f98b0010 
data = 0x7f74f984e010 
data = 0x7f74f93c4010 
data = 0x929010 
data = 0x98aaa0 
data = 0x9ec530 
data = 0xa4dfc0 
data = 0xaafa50 

的行为是相同的,如果我编译成C程序(.C,GCC)和作为C++程序(.C,克++ )。如果我用malloc()替换posix_memalign(),行为是一样的。

任何想法是怎么回事?谢谢!

我使用Linux 3.2.0/x86_64(Ubuntu)和gcc 4.6.3。

+2

您是否认为实际上释放了所有的分配,而不仅仅是最后一个?而且绝对不能保证分配与其他分配有任何特定的顺序或特定的地点。 – 2014-12-13 17:15:52

+0

@MatsPetersson:在这种情况下(posix_memalign(),然后立即释放())切换到低地址也发生在第一次空闲后。 – Ralf 2014-12-13 17:21:22

+0

这会回答这个问题:http://stackoverflow.com/questions/1119134/how-do-malloc-and-free-work? – noxmetus 2014-12-13 17:33:10

回答

1

此行为是完全有效的,您的代码不应该依赖于以任何特定模式分配的内存。

它归结为分配功能的内部实现细节,但一个可能的解释是:

  • free功能着眼于多少内存已分配给进程与它是多么的实际使用,以决定是否应释放某些内存(供其他进程使用)。
  • 在分析过程中,free更改了分配器使用的一些内部状态变量,即使没有实际释放内存。
  • 因此,将来调用分配函数的行为与未调用free时的行为不同。
+0

所以你的意思是,只要第一个free()被调用,就会缩减高内存范围(并将剩余的内存传递回内核),然后切换到低内存范围并从内核获取新内存? – Ralf 2014-12-13 17:49:27

+0

嗯,它不能将那么高的内存块返回给内核,因为你仍然在那里分配了东西。但它可以改变它使用的任何内部状态,以决定首先检查哪个块用于未来的分配。可能是因为低位块一直有空闲空间,但之前它先检查高位块(也有空闲空间)。 – Wyzard 2014-12-13 17:51:46

+1

我可以添加一个新观察:如果分配的内存块较小(例如,只有10000个浮点数而不是100000个),posix_memalign总是返回低范围内的地址。我在第一个/第二个循环中测试了不同的块大小。行为奇怪:100000/100000 - >高/低地址,10000/10000 - >低/低地址,10000/100000 - >低/高地址,100000/1000000 - >高/高地址。看起来像malloc手册页(128 kB)中提到的MMAP_THRESHOLD,但我仍然不理解不同的地址范围以及为什么在第一个free()后切换行为。 – Ralf 2014-12-17 15:51:27