繁体   English   中英

C中奇怪的malloc行为

[英]strange malloc behavior in C

我试图创建一个动态比例的矩阵,并在这里初始化它是我用来分配内存和初始化的代码:

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;

这个,工作得很好,问题是,如果我尝试创建一个short类型的矩阵 - 我在init第一次传递时得到分段错误。

这是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:为了清晰的代码,我放弃了安全检查,索引变量和边界声明。

谢谢,
亚历克斯

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

当您将malloc()的返回值malloc()short ,返回的指针将被截断以适合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;

你使用什么编译器,它不会尖叫你所有这些明显的错误?

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

你必须从这个错误中吸取教训。 它说如下: 永远不会投出'malloc'的结果

此外,这是一个更好的实践gudeline的一部分,只要有可能,最好遵循: 除了声明之外,不要在代码中提及类型名称

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

  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'的声明而不是其他的。

(当然,在这段代码中可以改进更多内容,但我只是想解决错误的直接原因。)

您正在将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);

是的,你做错了什么。

 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; 

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM