为什么在分配大量char *时内存大小翻倍?

时间:2014-01-28 09:04:41

标签: c linux malloc

我分配了一个char *的2D数组,每个字符串长度为12 50行和2000000列。

让我们计算一下: 50*2000000 * (12(length)+8(for pointer))。我用64位。

50 * 2000000 * 20 = 2000000000位... - > 2 GB。

当我检查内存监视器时,它显示该过程需要4 GB (分配后发生的一切)

这是代码:

int col=2000000,row=50,i=0,j=0;
char *** arr;
arr=(char***)malloc(sizeof(char**)*row);
for(i=0;i<row;i++)
{
arr[i]=(char ** )malloc(sizeof(char*)*col);
    for(j=0;j<col;j++)
     {
         arr[i][j]=(char*)malloc(12);
         strcpy(arr[i][j],"12345678901");
         arr[i][j][11]='\0';
     }
}

可能来自Linux中的分页吗?

2 个答案:

答案 0 :(得分:4)

每次调用malloc都会占用比你要求更多的内存。 Malloc需要在某处存储有关已分配空间的内部信息,如分配空间的大小,有关邻居块的一些信息等。另外(很可能)每个返回的指针都对齐到16个字节。在我的估计中,每个12字节的分配需要32字节的内存。如果要保存内存,请在一个malloc中分配所有字符串,并将它们分成每12个大小。 请尝试以下方法:

int col=2000000,row=50,i=0,j=0;
char *** arr;
arr= malloc(sizeof(*arr)*row);
for(i=0;i<row;i++)
{ 
  arr[i]= malloc(sizeof(*arr[i])*col);
  char *colmem = malloc(12 * col);
  for(j=0;j<col;j++)
  {
     arr[i][j] = colmem + j*12;
     strcpy(arr[i][j],"12345678901");
  }
}

答案 1 :(得分:2)

我会从头开始重写代码。出于某种原因,大约99%的C程序员不知道如何动态地正确分配真正的2D数组。我甚至不确定我是1%的人之一,但是让我们试一试:

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

int main()
{
  const int COL_N = 2000000;
  const int ROW_N = 50;

  char (*arr)[ROW_N] = malloc( sizeof(char[COL_N][ROW_N]) );

  if(arr == NULL)
  {
    printf("Out of memory");
    return 0;
  }

  for(int row=0; row<ROW_N; row++)
  {
    strcpy(arr[row], "12345678901");
    puts(arr[row]);
  }

  free(arr);

  return 0;
}

这里的重要部分是:

  • 你应该总是在相邻的内存单元中分配多维数组,或它们不是数组,而是基于指针的查找表。因此,您只需要一个malloc调用。
  • 这应该节省一点内存,因为你只需要一个指针并在堆栈上分配它。没有在堆上分配指针。
  • 强制转换malloc的返回值是没有意义的(但在现代编译器上并不危险)。
  • 确保malloc实际工作,特别是在分配大量内存时。
  • strcpy复制空终止,您不需要手动执行。
  • 不需要嵌套循环。您想要分配2D阵列,而不是3D阵列。
  • 使用free()总是清理自己的混乱,即使操作系统可能会为你做这件事。