难以在堆上创建连续的2D数组

时间:2016-04-09 00:16:26

标签: c arrays segmentation-fault malloc

我目前正在堆上实现floats的N x 2矩阵,如下所示:

float **matrix = malloc(sizeof(float*) * n_cols);

for (int i = 0; i < n_cols; ++i) {
    matrix[i] = malloc(sizeof(float) * 2);
}

matrix的元素在内存中不连续,使得这个数据结构缓存不友好(据我理解)。我试图重写上面的内容,在堆上创建一个真正的2D数组。基于之前的一些SO帖子,我尝试了以下内容:

float (*matrix)[2] = malloc(sizeof(float) * n_cols * 2);

但是,当我运行代码时,这会导致分段错误。

2 个答案:

答案 0 :(得分:2)

如果您希望整个数组是连续的,那么您需要按如下方式声明它。

  float *matrix = malloc(n1 * n2 * sizeof(float));

这有用吗?注意矩阵的第二种分配方式。

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

int main(void) {
  size_t r = 0;
  size_t c = 0;
  int rows    = 82;
  int columns = 30;
  float *matrix = malloc(rows * columns * sizeof(float));
  for(r = 0; r < rows; r++) {
    printf("%zu - ", r); 
    for(c = 0; c < columns; c++) {
      printf("%zu|", c); 
      matrix[r + r*c] = 1.0;
    }   
    printf("\n"); 
  }

  float **matrix2 = malloc(rows * sizeof(float*));

  for(r = 0; r < rows; r++) {
    matrix2[r]    = malloc(columns * sizeof(float));
  }
  for(r = 0; r < rows; r++) {
    printf("%zu - ", r); 
    for(c = 0; c < columns; c++) {
      printf("%zu|", c); 
      matrix2[r][c] = 1.0;
    }   
    printf("\n"); 
  }
  free(matrix);
  for(r = 0; r < rows; r++) {
    free(matrix2[r]);    
  }
  free(matrix2);
  return 0;
}   

你可以在这里找到代码的基准......

https://github.com/harryjackson/doc/blob/master/c/cache_locality_2d_array_test.c

答案 1 :(得分:0)

我想你想要这样的东西。

float ** matrix = malloc(sizeof(float) * ((n_col * 2) + (n_col * sizeof(float*));

for(i = 0; i < n_col; i++)
{
    matrix[i] = matrix + (n_col *sizeof(float*)) + ((i * 2) *sizeof(float)); 
}

矩阵的大小为2 * n_col,但矩阵的第一个索引将是指向列的指针。您必须为这些指针分配额外的空间。这是(n_col * sizeof(float *))发挥作用的地方。每行的大小(2 * sizeof(float)),因此矩阵中索引的每个行都需要指向远离最后一个的内存数组(2 * sizeof(float))字节。

它看起来像这样。

m [0] m [1] m [2] 矩阵矩阵+ 1 *(2 * sizeof(float))矩阵+ 2 *(2 * sizeof(float))

第二个索引将m [x]指向的内存位置引入内存。