声明两个大的二维数组给出了分段错误

问题描述:

我试图为两个2d数组声明和分配内存。但是,当试图将值赋给itemFeatureQ [39] [16816]时,我得到了一个分割库。我无法理解,因为我有2GB的RAM,只有19MB的堆。这是代码;声明两个大的二维数组给出了分段错误

double** reserveMemory(int rows, int columns) 
{ 
    double **array; 
    int i; 
    array = (double**) malloc(rows * sizeof(double *)); 
    if(array == NULL) 
    { 
     fprintf(stderr, "out of memory\n"); 
     return NULL; 
    } 
    for(i = 0; i < rows; i++) 
    { 
     array[i] = (double*) malloc(columns * sizeof(double *)); 
     if(array == NULL) 
     { 
      fprintf(stderr, "out of memory\n"); 
      return NULL; 
     } 
    } 

    return array; 

} 

void populateUserFeatureP(double **userFeatureP) 
{ 
    int x,y; 

    for(x = 0; x < CUSTOMERS; x++) 
    { 
     for(y = 0; y < FEATURES; y++) 
     { 
      userFeatureP[x][y] = 0; 
     } 
    } 
} 

void populateItemFeatureQ(double **itemFeatureQ) 
{ 
    int x,y; 

    for(x = 0; x < FEATURES; x++) 
    { 
     for(y = 0; y < MOVIES; y++) 
     { 
      printf("(%d,%d)\n", x, y); 
      itemFeatureQ[x][y] = 0; 
     } 
    } 
} 

int main(int argc, char *argv[]){ 

    double **userFeatureP = reserveMemory(480189, 40); 
    double **itemFeatureQ = reserveMemory(40, 17770); 

    populateItemFeatureQ(itemFeatureQ); 
    populateUserFeatureP(userFeatureP); 

    return 0; 
} 

你有几个错字 - 变化:

array[i] = (double*) malloc(columns * sizeof(double *)); 
    if(array == NULL) 

到:

array[i] = (double*) malloc(columns * sizeof(double)); 
    if(array[i] == NULL) 

一种更好的方式来处理二维的东西的内存分配,如果它是大是做什么像这样:

// small fix to this, added pointer de-reference 
// if you iterate over x in your outer loop you should 
// change the index part to (a)->h*(x) + (y) 
// but only do one or the other 
#define IDX_DBL2D(a, x, y) (*((a)->d[(a)->w*(y) + (x)])) 

struct dbl2d {int w,h; double[] d; }; 

struct dbl2d *alloc_2d_dbl(int w, int h) { 
    struct dbl2d *r = malloc(sizeof(struct dbl2d) + sizeof(double)*w*h); 
    r->w = w, r->h = h; 
    return r; 
} 

th有点像编译器在声明2d数组时所做的事情(但是它的索引会以其他方式循环)

这将使用更少的内存(不需要存储所有这些行指针),并把一切都在一起

当这样,如果你写bar = foo[x][y];和foo是n×m的那么编译器开启编译器创建它知道它有多大,每一路的固定大小的二维数组为bar = *(foo + x*m + y)但这只适用于东西在编译器知道你的数组是什么形状,所以我上面定义的基本上是一个数组,它的尺寸与它一起。

索引计算的工作原理如果你把foo当作一个数组数组,每行的大小为sizeof(*foo)*width(取决于你制作x或y的天气是第一次坐标,这里我用x来表示,因为我习惯用图像这就是那里使用的惯例),所以如果你乘以你的y坐标一行中的元素的数量,你可以跳过'y'行,那么你可以通过添加x来获得行内的元素。

用例:

void populateUserFeatureP(struct dbl2d *userFeatureP) 
{ 
    int x,y; 

    for(x = 0; x < CUSTOMERS; x++) 
    { 
     for(y = 0; y < FEATURES; y++) 
     { 
      IDX_DBL2D(userFeatureP, x, y) = 0; 
     } 
    } 
} 

void populateItemFeatureQ(struct dbl2d *itemFeatureQ) 
{ 
    int x,y; 

    for(x = 0; x < FEATURES; x++) 
    { 
     for(y = 0; y < MOVIES; y++) 
     { 
      printf("(%d,%d)\n", x, y); 
      IDX_DBL2D(itemFeatureQ, x, y) = 0; 
     } 
    } 
} 

int main(int argc, char *argv[]){ 

    struct dbl2d *userFeatureP = alloc_2d_dbl(480189, 40); 
    struct dbl2d *itemFeatureQ = alloc_2d_dbl(40, 17770); 

    populateItemFeatureQ(itemFeatureQ); 
    populateUserFeatureP(userFeatureP); 

    return 0; 
} 
+0

你的选择是非常有趣的。请您详细解释代码的解释。以一个使用示例。 – pfdevilliers 2010-06-17 18:21:40

+0

@pfdevil完成.... – Spudd86 2010-06-23 18:44:55

在分配二维数组,一个漂亮的技巧是,你只能使用2个mallocs。

double** reserveMemory(int rows, int columns) { 
    double **array, *data; 
    int i; 
    array = (double**) malloc(rows * sizeof(double *)); 
    data = (double*) malloc(rows * columns * sizeof(double)); 
    for(i = 0; i < rows; i++){ 
     array[i] = data + i * columns; 
    }  
    return array;  
} 

这也可以使用二维数组当作一维数组