Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

strange malloc behavior in C

Tags:

c

int

malloc

short

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

like image 300
Alex Avatar asked Aug 14 '26 08:08

Alex


2 Answers

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;
like image 144
Alex B Avatar answered Aug 16 '26 23:08

Alex B


What compiler are you using that it doesn't scream at you about all these obvious errors?

gcc -Wall produced five warning messages with this code.

#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;
}

Gives me

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

Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!