[英]Unexpected data/unexpected segfault in a dynamically allocated array (for two dimensional use)
I am trying to create a 2D matrix in C (basically a dynamically allocatable 2d array of any given size) in both the most efficient and clean way possible. 我试图以最有效和最简洁的方式在C中创建2D矩阵(基本上是任何给定大小的动态可分配2d数组)。 I had implemented such a thing in a larger project I am working on, but was having issues, and was able to narrow it down to the following.
我已经在一个较大的项目中实现了这样的事情,但是遇到了问题,因此可以将其范围缩小到以下范围。
I decided to malloc a giant array (I called it data), and then make an array of pointers (i called it cell) to be able to address the data in the big array in such a way that would make sense in a two-dimensional context (as in matrix[x][y] instead of data[ugly pointer arithmetic each time].) I thought this would be a good idea because it only calls malloc once, and so it would be faster, also, the allocated memory is in one consecutive block, which I believe (not too knowledgeable here) is a really good thing on some systems because of overhead in keeping track of allocated memory blocks. 我决定先分配一个巨型数组(我称其为数据),然后创建一个指针数组(即其称为单元格),以便能够以这样的方式在大数组中寻址数据:维上下文(如在matrix [x] [y]中,而不是data [每次都使用丑陋的指针算术]。)我认为这将是一个好主意,因为它只调用一次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");
}
}
When I run the above program as ./a.out 10 10
there is no problem, but when I specify 30 20 instead of 10 10, I run into some issues. 当我以
./a.out 10 10
运行上述程序时,没有问题,但是当我指定30 20而不是10 10时,遇到了一些问题。
On MacOSX (10.6.7) I get: 在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
and then it exits properly. 然后它正确退出。
On OpenBSD (4.7) I get this far: 在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
and then it just segfaults 然后它只是段错误
My initial thought was that it was just some issue when allocating big enough blocks of memory that they cross page boundaries, but when I use 50 50
as the size, it runs fine. 我最初的想法是,当分配足够大的内存块以使其跨越页面边界时,这只是一个问题,但是当我使用
50 50
作为大小时,它运行良好。
I've narrowed it down this far, and tried googleing (not quite sure what it is I should be searching for though :| ) and asked a few of my friends, but this has them all stumped. 我已经将其缩小到目前的范围,并尝试使用Google搜索(虽然不太确定我应该搜索的是:|),并询问了我的几个朋友,但这使他们都陷入了困境。
I found C. Segmentation Fault when function modifies dynamically allocated 2d array int matrix with pointers in C - memory allocation confusion but they were not relevant (as far as I can tell). 我发现了C. Segmentation Fault,当函数 用C中的指针 修改动态分配的2d数组 int矩阵时-内存分配混乱,但它们并不相关(据我所知)。
If somebody could please point me in the right direction, perhaps point out the problem or point me to some relevant documentation, I would be very grateful. 如果有人可以指出正确的方向,或者指出问题或指向一些相关的文档,我将不胜感激。
for (i = 0; i < sizeX; i++) {
mat->cell[i] = mat->data + mat->sizeX * i;
}
One of these SizeX'es needs to be a sizeY. 这些SizeX之一必须是sizeY。
for (i = 0; i < sizeX; i++) {
mat->cell[i] = mat->data + mat->sizeX * i;
}
Imagine if sizeX is 100 and sizeY is 2. Here, you're laying out sizeX rows, 100 of them, each sizeX integers, 100 of them. 想象一下,如果sizeX是100,sizeY是2。在这里,您要布局sizeX行,其中100行,每个sizeX整数,其中100行。 Ooops.
哎呀
That mat->sizeX
should be mat->sizeY
. 该
mat->sizeX
应该是mat->sizeY
。 You have sizeX rows, each with sizeY elements in them. 您有sizeX行,每行中都有sizeY个元素。 So you need to skip forward sizeY integers to get to the next row.
因此,您需要跳过正向的sizeY整数才能到达下一行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.