HEAP 上的数组分配(单独分配与......连续分配?)

Array allocation on HEAP (Separate allocation vs ... contiguous?)

在这个回答中:

此人用两种方式在 HEAP 上分配数组:

int main(){
    const int n = 100000;

#ifdef ALLOCATE_SEPERATE
    double *a1 = (double*)malloc(n * sizeof(double));
    double *b1 = (double*)malloc(n * sizeof(double));
    double *c1 = (double*)malloc(n * sizeof(double));
    double *d1 = (double*)malloc(n * sizeof(double));
#else
    double *a1 = (double*)malloc(n * sizeof(double) * 4);
    double *b1 = a1 + n;
    double *c1 = b1 + n;
    double *d1 = c1 + n;
#endif
}

这两种分配方式有什么区别?

else中的第二种方法是连续分配块吗?

(我专注于 Linux 观点;根据您的 operating system and/or 编译器实现进行调整)

您问题中的代码具有类似 C 语言的外观和感觉。正版 C++ 将使用 new,即在非 ALLOCATE_SEPARATE 情况下类似于

 double *a1 = new double[4*n];
 double *b1 = a1 + n;

如果内存分配失败,您将得到一个 std::bad_alloc 异常。

What is the difference between the two ways of allocation?

ALLOCATE_SEPARATE 案例正在对 malloc 进行四次调用。请注意:

  • 每个人 malloc 都可能失败,您应该检查一下,例如与

    double *a1 = (double*)malloc(n * sizeof(double));
    if (!a1) { perror("malloc a1"); exit (EXIT_FAILURE); };
    

    假设您需要一些 C 代码。并且 malloc 可以 失败,例如当内核无法提供更多虚拟内存时,例如因为 mmap(2) failed, some limits have been reached (see getrlimit(2)...), swap space has been exhausted (with memory overcommit being disabled), etc.... Read about paging & page cache, and the man pages of malloc(3),特别是它的 NOTES 部分....顺便说一句,您的计算机有 finite 资源,所以它们可能会溢出。在便宜的笔记本电脑上,您将无法在 2015 年成功 malloc 10 TB 的内存(并可靠地使用内存区域)。当然,对于 n = 100000malloc通常成功。

  • 在实践中,如果您要求 大量 内存(千兆字节),malloc 可能会失败,但某些操作系统有 memory overcommitment(我个人不喜欢这个功能并在我的 Linux 系统上禁用)并给你一些指导,即使没有足够的 space 用于巨大的内存区域

  • 万一n * sizeof(double)溢出size_t,灾难就会发生。

ALLOCATE_SEPARATE 要求 malloc(n * sizeof(double) * 4) 并且可能会溢出 n 的较小值(在实践中仍然很大)。 * 4 是必需的,因为我们要求足够的 space 来容纳四个不同的非 aliasing pointers 和它们的非重叠内存区域。

Is the second method in else block allocating in a contiguous manner?

当然可以(正如我所说,对于较小的 n 值可能会溢出或失败,例如,当 n * sizeof(double) * 4n * 32 在 32 位 Linux(即 Android)平板电脑大于 3 GB,甚至可能是 1 GB。

实际上,您应该使用 C++11 containers 和代码:

#include <vector>
int main(){
   const int n = 100000;
   std::vector<double> vec(n);

vector 的数据将位于堆中,vec 的析构函数将释放它。

当然heap data is allocated in the address space of the virtual memory of your process (on Linux, probably using the mmap(2) -or sometimes sbrk- syscall).