2

我正在尝试创建一个具有动态比例的矩阵并在此处对其进行初始化,这是我用于分配内存和初始化的代码:

int **matrix;
//mem allocation
matrix=(int*)malloc(sizeof(int*)*mat_w);
for (i=0;i<mat_w;i++)
    matrix[i]=(int)malloc(sizeof(int)*mat_h);
//init
for (i=0;i<mat_w;i++)
    for (j=0;j<mat_h;j++)
        matrix[i][j]=0;

这个,工作正常,问题是,如果我尝试创建一个短类型的矩阵 - 我在初始化第一遍时遇到分段错误。

这是 C 语言问题还是我做错了什么?

类型矩阵的代码short

short **matrix;
//mem allocation
matrix=(short*)malloc(sizeof(short*)*mat_w);
for (i=0;i<mat_w;i++)
    matrix[i]=(short)malloc(sizeof(short)*mat_h);
//init
for (i=0;i<mat_w;i++)
    for (j=0;j<mat_h;j++)
        matrix[i][j]=0;

PS:为了代码的清晰,我放弃了安全检查、索引变量和边界声明。

谢谢,
亚历克斯

4

6 回答 6

17

您对返回值的强制转换malloc()无效。在第一种情况下它们应该是int**和,在第二种情况下应该是和。int*short**short*

当您将返回值转换为malloc()toshort时,返回的指针会被截断以适合short值,然后分配给short*指针,从而产生指向无效内存位置的指针值。因此,您在尝试访问它时会遇到分段错误。

有了int,你就很幸运了,因为在你的平台上很可能sizeof(int)==sizeof(int*),所以一个由转换为返回的指针malloc()不会int被截断,它会默默地工作。它很可能会在 64 位平台上以类似的方式崩溃。

应该:

short **matrix;
matrix=(short**)malloc(sizeof(short*)*mat_w);
for (i=0;i<mat_w;i++)
    matrix[i]=(short*)malloc(sizeof(short)*mat_h); 
for (i=0;i<mat_w;i++)
    for (j=0;j<mat_h;j++)
        matrix[i][j]=0;

如果您的代码是纯 C(不是 C++),则可以省略强制转换,因为在 C 中,从void*任何其他指针类型强制转换都是有效的。

short **matrix;
matrix = malloc(sizeof(short*)*mat_w);
for (i=0;i<mat_w;i++)
    matrix[i] = malloc(sizeof(short)*mat_h); 
for (i=0;i<mat_w;i++)
    for (j=0;j<mat_h;j++)
        matrix[i][j]=0;
于 2009-10-12T12:27:33.993 回答
15

您使用的是什么编译器,它不会对所有这些明显的错误大喊大叫?

gcc -Wall使用此代码产生了五条警告消息。

#include <stdlib.h>

int main ()
{
    int mat_w = 99;
    int mat_h = 666;
    int i;
    int j;

    int **imatrix;
    short **smatrix;
    //mem allocation
    imatrix=(int*)malloc(sizeof(int*)*mat_w);
    for (i=0;i<mat_w;i++)
    imatrix[i]=(int)malloc(sizeof(int)*mat_h);
    //init
    for (i=0;i<mat_w;i++)
    for (j=0;j<mat_h;j++)
        imatrix[i][j]=0;

    //mem allocation
    smatrix=(short*)malloc(sizeof(short*)*mat_w);
    for (i=0;i<mat_w;i++)
    smatrix[i]=(short)malloc(sizeof(short)*mat_h);
    //init
    for (i=0;i<mat_w;i++)
    for (j=0;j<mat_h;j++)
        smatrix[i][j]=0;
    return 0;
}

给我

malloc.c: In function 'main':
malloc.c:13: warning: assignment from incompatible pointer type
malloc.c:15: warning: assignment makes pointer from integer without a cast
malloc.c:22: warning: assignment from incompatible pointer type
malloc.c:24: warning: cast from pointer to integer of different size
malloc.c:24: warning: assignment makes pointer from integer without a cast
于 2009-10-12T12:35:15.743 回答
6

你必须从这个错误中吸取一个严肃的教训。它说以下内容:永远不要投射 'malloc' 的结果

此外,这是一个更大的良好实践准则的一部分,最好尽可能遵循:永远不要在代码中提及类型名称,除非在声明中

这就是您的代码从一开始就应该看起来的样子

  int **matrix;

  matrix = malloc(mat_w * sizeof *matrix);
  for (i = 0; i < mat_w; i++)
    matrix[i] = malloc(mat_h * sizeof *matrix[i]);

  for (i = 0; i < mat_w; i++)
    for (j = 0; j < mat_h; j++)
      matrix[i][j] = 0;

请注意,为了在此版本中从“int”切换到“short”,您只需要更改“matrix”的声明即可。

(当然,这段代码还有更多可以改进的地方,但我只是想解决错误的直接原因。)

于 2009-10-12T17:45:03.323 回答
5

您正在将您的值转换int**int*malloc 的返回值(简称相同)。malloc应该这样使用:

matrix = (int**)malloc(sizeof(int*) * mat_w);

或者

matrix = (short**)malloc(sizeof(short*) * mat_w);

矩阵内的每个分配都相同:

matrix[i] = (int*)malloc(sizeof(int) * mat_h);

或者

matrix[i] = (short*)malloc(sizeof(short) * mat_h);
于 2009-10-12T12:28:01.450 回答
2

是的,你做错了什么。

 int *matrix;

表示这matrix是一个整数数组。如果你希望它是一个整数数组的数组,你应该像这样声明它:

 int **matrix;
 //mem allocation
 matrix=(int**)malloc(sizeof(int*)*mat_w);
 for (i=0; i<mat_w; i++)
     matrix[i]=(int*)malloc(sizeof(int)*mat_h);
 //init
 for (i=0; i<mat_w; i++)
     for (j=0; j<mat_h; j++)
         matrix[i][j]=0; 

当然,如果你事先知道矩阵的维度,就这样做吧:

int matrix[mat_w][mat_h];
 //init
 for (i=0; i<mat_w; i++)
     for (j=0; j<mat_h; j++)
         matrix[i][j]=0; 
于 2009-10-12T12:29:52.617 回答
0

sizeof(int)等于特定系统的总线宽度。您正在尝试将 32 位(或 64,具体取决于您的平台)地址值放入 16 位分配的内存中。

查看 Checkers 帖子中的第二个示例。这是内存分配的正确和可取的方式。

于 2009-10-12T12:29:48.107 回答