Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ posix_memalign/malloc在第一次调用free后分配较低的地址_C++_C - Fatal编程技术网

C++ posix_memalign/malloc在第一次调用free后分配较低的地址

C++ posix_memalign/malloc在第一次调用free后分配较低的地址,c++,c,C++,C,我有点担心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, 100

我有点担心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;
}
< >如果编译为C程序(.c,gccc)和C++程序(.c,g++),则行为相同。如果我用malloc()替换posix_memalign(),则行为相同

知道发生了什么吗?谢谢


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

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

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

  • free
    函数查看已分配给进程的内存量与实际使用的内存量,以决定是否应释放一些内存(供其他进程使用)
  • 在进行该分析的过程中,
    free
    更改分配器使用的一些内部状态变量,即使实际上没有释放内存
  • 因此,未来对分配函数的调用与未调用
    free
    时的行为不同

  • 你是否考虑释放所有的分配,而不仅仅是最后一个?而且绝对不能保证分配相对于其他分配是以任何特定的顺序或任何特定的位置进行的。@MatsPeterson:在这种情况下(posix_memalign(),然后立即释放()),在第一次释放之后也会切换到较低的地址。@noxmetus:谢谢链接,但不,我没有找到解决我问题的具体方法。[编辑:]在我看来,出于效率原因(不调用brk()或sbrk()),分配似乎是从虚拟地址空间上端的某个保留区域提供的。这实际上可以在没有任何堆管理的情况下完成。一旦调用free(),它就必须使用堆管理并切换到不同的地址。实际上,我从一开始就希望有低地址,因为堆从代码和静态数据范围的正上方开始,然后向上增长。@Yakk。作者没有说这是个问题,他说他很担心。一种莫名其妙的行为会让任何好奇的人感到担忧。@雅克:为了解释我为什么问这个问题:几年前我也有过类似的问题。我们使用的一些库附带了自己的堆管理系统,基本上是旧版本libc(phantastic idea)的副本。它提供了一个链接到代码的free(),但还没有posix_memalign(),因此它是从libc使用的。因此,我们实际上有两个堆管理系统在两个不同的地址范围内工作(类似的效果如图所示)。当然,它坠毁了。我只是担心这里会发生类似的事情,虽然我没有链接任何库,但它应该是libc。你的意思是,一旦调用第一个free(),它就会缩减高内存范围(并将其余的传递回内核),然后切换到低内存范围并从内核获取新内存?嗯,它无法将高内存块返回到内核,因为您仍然在那里分配了一些东西。但它可以改变它用来决定首先检查哪个块以备将来分配的任何内部状态。可能是低块一直都有可用空间,但它之前先检查高块(也有可用空间)。我可以补充一个新的观察:如果分配的内存块更小(例如,只有10000个浮点值而不是100000个浮点值),posix_memalign总是从低范围返回地址。我在第一个/第二个循环中测试了不同的块大小。这种行为很奇怪:100000/100000->高/低地址,10000/10000->低/低地址,10000/100000->低/高地址,100000/1000000->高/高地址。看起来像malloc手册页中提到的MMAP_阈值(128 kB),但我仍然不理解不同的地址范围,以及为什么在第一个free()之后行为会切换。
    % ./aligned
    data = 0x7f74f9974010
    data = 0x7f74f9912010
    data = 0x7f74f98b0010
    data = 0x7f74f984e010
    data = 0x7f74f93c4010
    data = 0x929010
    data = 0x98aaa0
    data = 0x9ec530
    data = 0xa4dfc0
    data = 0xaafa50