Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.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 声明两个大型2d数组会导致分段错误_C_Arrays - Fatal编程技术网

C 声明两个大型2d数组会导致分段错误

C 声明两个大型2d数组会导致分段错误,c,arrays,C,Arrays,我试图为两个2d数组声明和分配内存。但是,当尝试为itemFeatureQ[39][16816]赋值时,我得到了一个分段vault。我无法理解,因为我有2GB的RAM,堆上只使用19MB。这是代码 double** reserveMemory(int rows, int columns) { double **array; int i; array = (double**) malloc(rows * sizeof(double *)); if(array ==

我试图为两个2d数组声明和分配内存。但是,当尝试为itemFeatureQ[39][16816]赋值时,我得到了一个分段vault。我无法理解,因为我有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;
}
double**reservemory(int行、int列)
{
双**阵列;
int i;
数组=(双**)malloc(行*sizeof(双*);
if(数组==NULL)
{
fprintf(stderr,“内存不足”);
返回NULL;
}
对于(i=0;i
您有几个输入错误-更改:

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


如果2D文件较大,处理其内存分配的更好方法是执行以下操作:

// 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;
}
这有点像编译器在声明2d数组时所做的操作(但它的索引是相反的)

这将使用更少的内存(不需要存储所有这些行指针)并将所有内容保持在一起

当编译器创建一个固定大小的2d数组时,它知道它的大小,因此如果您编写
bar=foo[x][y]
和foo是nxm,然后编译器将其转换为
bar=*(foo+x*m+y)
,但是这只适用于编译器知道数组形状的情况,所以我上面定义的基本上是一个数组,其中包含它的维度

索引计算之所以有效,是因为如果您将foo视为一个数组数组,则每行的大小
sizeof(*foo)*宽度
(取决于您是否将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;
}
void populateUserFeatureP(结构dbl2d*userFeatureP)
{
int x,y;
对于(x=0;x<客户;x++)
{
对于(y=0;y
在分配2d数组时,一个很好的技巧是只能使用2个malloc

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;    
}
double**reservemory(int行、int列){
双**数组,*数据;
int i;
数组=(双**)malloc(行*sizeof(双*);
数据=(双*)malloc(行*列*大小(双));
对于(i=0;i

这也可用于将2d阵列视为1d阵列

您的选择非常有趣。你能详细解释一下密码吗。通过一个使用示例。
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;    
}