动态分配的数组中的意外数据/意外段错误(用于二维使用)

时间:2011-10-12 22:40:55

标签: c arrays pointers matrix

我正在尝试以最有效和最干净的方式在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,但它们并不相关(据我所知)。

如果有人可以指出我正确的方向,或许指出问题或指出我的一些相关文件,我将非常感激。

2 个答案:

答案 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整数才能到达下一行。