Search code examples
cmallocintshort

strange malloc behavior in C


I am trying to create a matrix with dynamic proportions and to initialize it here is the code I am using to allocate memory and initialization:

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;

This , works fine , question is , if I try to create a matrix of type short - I get a segmentation error on the init first pass.

Is this a C language issue or am I doing something wrong?

Code for matrix of type 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;

P.S.: I dropped safety checks , index variables and boundary declarations for clarity of code.

Thanks,
Alex


Solution

  • Your casts for the return value of malloc() are invalid. They should be int** and int* in the first case, and short** and short* in the second.

    When you cast the return value of malloc() to short, a pointer returned gets truncated to fit in short value, and then gets assigned to a short* pointer, yielding a pointer value pointing to an invalid memory location. Therefore you get a segmentation fault trying to access it.

    With int, you are getting lucky, since on your platform most probably sizeof(int)==sizeof(int*), so that a pointer returned by malloc() casted to int is not truncated and it all silently works. It would most probably crash in a similar fashion on a 64-bit platform.

    Should be:

    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;
    

    If your code is pure C (not C++), you can omit the casts, as in C casting from void* to any other pointer type is valid.

    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;