为什么连续调用new 不分配连续内存?

我使用Ubuntu 14.04 64位。 这是我的C ++代码,看看如何使用内存

int main() { int **ptr; ptr = new int* [2]; cout << &ptr << " -> " << ptr << endl; for (int r = 1; r <= 2; r++) { ptr[r-1] = new int [2 * r]; cout << &ptr[r-1] << " -> " << ptr[r-1] << endl; for (int c = 0; c < 2 * r; c++) { ptr[r-1][c] = r * c; cout << &ptr[r-1][c] << " -> " << ptr[r-1][c] << endl; } } return 0; } 

这是我的输出:

 0x7fff09faf018 -> 0x1195010 0x1195010 -> 0x1195030 0x1195030 -> 0 0x1195034 -> 1 0x1195018 -> 0x1195050 0x1195050 -> 0 0x1195054 -> 2 0x1195058 -> 4 0x119505c -> 6 

我预计操作系统会连续分配内存。 所以ptr [0] [0]将在0x1195020,而不是0x1195030! 操作系统在0x1195020 – 0x119502F,0x1195038 – 0x0x119504F处使用什么?

Solutions Collecting From Web of "为什么连续调用new 不分配连续内存?"

因为:

  1. 在每个分配的内存块的开始和结尾处的一些空间通常用于簿记。 (特别是,许多分配器发现它有用于存储前面/后面块的大小,或指向它们的指针)。

  2. 内存分配器可以“四舍五入”分配的块的大小以使其更容易。 例如,7字节的分配可能会四舍五入到8个字节,甚至不是16或32。

  3. 内存块可能已经在非连续的位置可用。 (请记住,在运行main()之前,C运行时可能已经做了一些自己的内存分配。)

  4. 分配器可能有一个计划,用于布置内存,将下一个块放在“下一个”地址处将会被破坏。 (例如,它可能已经预留了这个内存来分配一个特定的大小。)

  5. 为什么要这样? 没有保证。 分配的内存可能会在任何地方结束。 (好吧,差不多。)不要做任何假设,只要让分配器说出去的地方就回忆起来,你就会好起来的。