0
votes

Rather simple memory allocation, but I can't my head around.

What is the difference between:

int **ans = (int**)malloc(sizeof(int*[numRows]));

and

int **ans = (int**)malloc(sizeof(int)*numRows); 

I get heap buffer overflow using the second version, but what is the actual difference here? I try to allocate x amount of memory block type int. The difference is

sizeof(int) * numRows

vs

sizeof(int * [numRows])

2
The cast (int**) is unnecessary.Robert Harvey
sizeof(int)*numRows) is a size of numRow ints. sizeof(int*[numRows]) is a size of array of pointers to int. Totally different thingsEugene Sh.
Yeah, that's what I was thinking. The two statements are not equivalent.Robert Harvey
You're trying to allocate an array of pointers, so the fundamental type is int * not int. Hence, the second one should be sizeof(int *) * numRows.user3386109
To avoid some of this, how about: int **ans = malloc(sizeof(*ans) * numRows);?Craig Estey

2 Answers

1
votes

In the first case

int **ans = (int**)malloc(sizeof(int*[numRows]));

there is allocated memory for an array of numRows elements of the type int *.

In the second case

int **ans = (int**)malloc(sizeof(int)*numRows); 

there is allocated memory for an array of numRows elements of the type int and the allocated memory is interpreted as an array of elements of the type int * instead of int. So you can invoke undefined behavior if you will suppose that the memory stores an array with elements of the type int * because in general sizeof( int * ) can be unequal to sizeof( int ). But even if they are equal such a call will only confuse readers of the code an will be a potential bug

0
votes

int * [numRows] is not a multiplication expression, it's a type - it's an array of pointer to int. So sizeof (int * [numRows]) is the size (in bytes) of an array of int * that's numRows elements wide.

sizeof (int) * numRows, OTOH, is a multiplication expression - you're multiplying the size of an int by the number of rows. So, let's make some assumptions:

numRows        == 10;
sizeof (int)   ==  4;  // common on most platforms
sizeof (int *) ==  8;  // common on most 64-bit platforms

So, sizeof( int * [numRows]) gives us the size of a 10-element array of int *, which would be 80. sizeof (int) * numRows gives us the size of 10 int objects, which is 40.

A cleaner and less error-prone way of writing that malloc call would be

int **ans = malloc( sizeof *ans * numRows );

Since ans has type int **, the expression *ans has type int *, so sizeof *ans is the same as sizeof (int *). So we're allocating enough space to hold numRows instances of int *.

Remember that sizeof is an operator, not a function - the syntax is

sizeof ( type-name ) |
sizeof expression

It's a unary operator, which has higher precedence than a multiplication operator, so

sizeof *ans * numRows

will be parsed as

(sizeof *ans) * numRows