我正在尝试以最有效和最干净的方式在C中创建一个2D矩阵(基本上是任何给定大小的动态可分配的2d数组)。我已经在我正在开展的一个更大的项目中实现了这样的事情,但是遇到了问题,并且能够将其缩小到以下范围。
我决定malloc一个巨大的数组(我称之为数据),然后创建一个指针数组(我称之为单元格),以便能够以一种有意义的方式处理大数组中的数据。二维上下文(如矩阵[x] [y]而不是数据[每次丑陋的指针算法]。)我认为这是一个好主意,因为它只调用一次malloc,所以它会更快,也是,分配的内存在一个连续的块中,我相信(在这里不太了解)在某些系统上是一件非常好的事情,因为跟踪分配的内存块会产生开销。
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
typedef struct {
unsigned int sizeX;
unsigned int sizeY;
int **cell;
int *data; /* FOR INTERNAL USE ONLY */
} matrix;
matrix * matrix_malloc(unsigned int, unsigned int);
void matrix_free(matrix *);
void matrix_zero(matrix *);
void matrix_print(matrix *);
int
main(int argc, char *argv[])
{
int y, x;
matrix *theMatrix = NULL;
if (argc != 3) {
fprintf(stderr, "usage: %s sizeX sizeY\n", argv[0]);
return 1;
}
x = atoi(argv[1]);
y = atoi(argv[2]);
if (x < 10 || y < 10) {
fprintf(stderr, "usage: sizeX and sizeY must be >= 10\n");
return 1;
}
if ((theMatrix = matrix_malloc(x, y)) == NULL)
return 1;
matrix_zero(theMatrix);
/* lots of modification of the contents of the matrix would happen here */
matrix_print(theMatrix);
matrix_free(theMatrix);
return 0;
}
matrix *
matrix_malloc(unsigned int sizeX, unsigned int sizeY)
{
int i;
matrix *mat;
if ((mat = malloc(sizeof(matrix))) == NULL) {
return NULL;
}
if ((mat->data = malloc(sizeX * sizeY * sizeof(int))) == NULL) {
free(mat);
mat = NULL;
return NULL;
}
if ((mat->cell = malloc(sizeX * sizeof(int *))) == NULL) {
free(mat->data);
free(mat);
mat = NULL;
return NULL;
}
mat->sizeX = sizeX;
mat->sizeY = sizeY;
for (i = 0; i < sizeX; i++) {
mat->cell[i] = mat->data + mat->sizeX * i;
}
return mat;
}
void
matrix_free(matrix *mat) {
free(mat->cell);
free(mat->data);
free(mat);
mat = NULL;
}
void
matrix_zero(matrix *mat)
{
memset(mat->data, 0, mat->sizeX * mat->sizeY * sizeof(int));
}
void
matrix_print(matrix *mat)
{
unsigned int x, y;
for (x = 0; x < mat->sizeX; x++) {
for (y = 0; y < mat->sizeY; y++)
printf("%d ", mat->cell[x][y]);
printf("\n");
}
}
当我以./a.out 10 10
运行上述程序时没有问题,但是当我指定30 20而不是10 10时,我遇到了一些问题。
在MacOSX(10.6.7)上,我得到:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 540024880 540024880 540024880 540024880 540024880 808465461 943207474 875896880 875704368 540031032
842216505 926168880 926425140 909719605 540031032 926234424 909325360 875896888 825438256 540160816 10 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
然后它正常退出。
在OpenBSD(4.7)上,我得到了这个:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
然后它只是段错误
我最初的想法是,在分配足够大的内存块时,它只是一些问题,它们跨越页面边界,但当我使用50 50
作为大小时,它运行正常。
我已经缩小了这一点,并尝试了谷歌(不太确定我应该搜索的是什么:|)并且问了我的一些朋友,但这让他们都感到难过。
我找到了C. Segmentation Fault when function modifies dynamically allocated 2d array int matrix with pointers in C - memory allocation confusion,但它们并不相关(据我所知)。
如果有人可以指出我正确的方向,或许指出问题或指出我的一些相关文件,我将非常感激。
答案 0 :(得分:4)
for (i = 0; i < sizeX; i++) {
mat->cell[i] = mat->data + mat->sizeX * i;
}
其中一个SizeX'es需要是sizeY。
答案 1 :(得分:3)
for (i = 0; i < sizeX; i++) {
mat->cell[i] = mat->data + mat->sizeX * i;
}
想象一下,如果sizeX为100且sizeY为2.这里,你要布局sizeX行,其中100行,每个sizeX整数,100行。糟糕!
mat->sizeX
应为mat->sizeY
。您有sizeX行,每行包含sizeY元素。因此,您需要跳过前进的sizeY整数才能到达下一行。