Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   Still having trouble with malloc (http://www.velocityreviews.com/forums/t315642-still-having-trouble-with-malloc.html)

10-06-2003 03:23 PM

Still having trouble with malloc
 
I fail to understand why that the memory allocated in the void
create(int **matrix) does not remain. I passed the address of matrix so
shouldn't it still have the allocated memory when it returns to main.
The problem i am having is understanding why the printf statement in the
code below gives the value. I would have expected it to be 123 which is
the value I set it to in the create. Thanx in advance.

void create(int **matrix);

int main(void)
{
int **matrix;
create(matrix);

printf("%d", matrix[1][1]); /* ? */
}

void create(int **matrix)
{ /*allocating mem for 2 by 3 int matrix*/
matrix = (int **)malloc(2*sizeof(int *));
matrix[0] = (int *)malloc(3*sizeof(int));
matrix[1] = (int *)malloc(3*sizeof(int));

matrix[1][1] = 123;
}



Joona I Palaste 10-06-2003 03:34 PM

Re: Still having trouble with malloc
 
raymis@hotmail.com scribbled the following:
> I fail to understand why that the memory allocated in the void
> create(int **matrix) does not remain. I passed the address of matrix so
> shouldn't it still have the allocated memory when it returns to main.
> The problem i am having is understanding why the printf statement in the
> code below gives the value. I would have expected it to be 123 which is
> the value I set it to in the create. Thanx in advance.


> void create(int **matrix);


> int main(void)
> {
> int **matrix;
> create(matrix);


> printf("%d", matrix[1][1]); /* ? */
> }


> void create(int **matrix)
> { /*allocating mem for 2 by 3 int matrix*/
> matrix = (int **)malloc(2*sizeof(int *));


This line above should be a clear indication of what is wrong.

> matrix[0] = (int *)malloc(3*sizeof(int));
> matrix[1] = (int *)malloc(3*sizeof(int));


> matrix[1][1] = 123;
> }


You are experiencing the C parameter passing model. In C, all parameters
are passed by value. Without exception. The fact that the value's type
is a pointer (such as in this case) does not magically transform pass by
value into pass by reference.
If you find yourself assigning a new value to a function parameter in
the function, such as you are doing above, it's pretty darn near certain
that you have a design fault. The assignment will have exactly zilch
effect outside the function, as the parameter is a separate entity from
what was inside the parantheses in the call statement.
Instead, pass a pointer to your matrix like this:
create(&matrix);
And write your create function like this:
void create(int ***matrix) /* note three * signs, not two */
{ /*allocating mem for 2 by 3 int matrix*/
*matrix = (int **)malloc(2*sizeof(int *));
(*matrix)[0] = (int *)malloc(3*sizeof(int));
(*matrix)[1] = (int *)malloc(3*sizeof(int));
(*matrix)[1][1] = 123;
}
Also remember to #include <stdlib.h>, in which case you can safely
drop the casts.

--
/-- Joona Palaste (palaste@cc.helsinki.fi) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/
"The large yellow ships hung in the sky in exactly the same way that bricks
don't."
- Douglas Adams

10-06-2003 04:02 PM

Re: Still having trouble with malloc
 
I thought I was passing by pointer when I call the function create(matrix).
Isn't matrix by itself the first element address of matrix
(&matrix[0][0]).Thanx again in advance.

Joseph

"Joona I Palaste" <palaste@cc.helsinki.fi> wrote in message
news:bls22e$5u6$1@oravannahka.helsinki.fi...
> raymis@hotmail.com scribbled the following:
> > I fail to understand why that the memory allocated in the void
> > create(int **matrix) does not remain. I passed the address of matrix so
> > shouldn't it still have the allocated memory when it returns to main.
> > The problem i am having is understanding why the printf statement in the
> > code below gives the value. I would have expected it to be 123 which is
> > the value I set it to in the create. Thanx in advance.

>
> > void create(int **matrix);

>
> > int main(void)
> > {
> > int **matrix;
> > create(matrix);

>
> > printf("%d", matrix[1][1]); /* ? */
> > }

>
> > void create(int **matrix)
> > { /*allocating mem for 2 by 3 int matrix*/
> > matrix = (int **)malloc(2*sizeof(int *));

>
> This line above should be a clear indication of what is wrong.
>
> > matrix[0] = (int *)malloc(3*sizeof(int));
> > matrix[1] = (int *)malloc(3*sizeof(int));

>
> > matrix[1][1] = 123;
> > }

>
> You are experiencing the C parameter passing model. In C, all parameters
> are passed by value. Without exception. The fact that the value's type
> is a pointer (such as in this case) does not magically transform pass by
> value into pass by reference.
> If you find yourself assigning a new value to a function parameter in
> the function, such as you are doing above, it's pretty darn near certain
> that you have a design fault. The assignment will have exactly zilch
> effect outside the function, as the parameter is a separate entity from
> what was inside the parantheses in the call statement.
> Instead, pass a pointer to your matrix like this:
> create(&matrix);
> And write your create function like this:
> void create(int ***matrix) /* note three * signs, not two */
> { /*allocating mem for 2 by 3 int matrix*/
> *matrix = (int **)malloc(2*sizeof(int *));
> (*matrix)[0] = (int *)malloc(3*sizeof(int));
> (*matrix)[1] = (int *)malloc(3*sizeof(int));
> (*matrix)[1][1] = 123;
> }
> Also remember to #include <stdlib.h>, in which case you can safely
> drop the casts.
>
> --
> /-- Joona Palaste (palaste@cc.helsinki.fi) ---------------------------\
> | Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
> | http://www.helsinki.fi/~palaste W++ B OP+ |
> \----------------------------------------- Finland rules! ------------/
> "The large yellow ships hung in the sky in exactly the same way that

bricks
> don't."
> - Douglas Adams




Joona I Palaste 10-06-2003 04:12 PM

Re: Still having trouble with malloc
 
raymis@hotmail.com scribbled the following:
> I thought I was passing by pointer when I call the function create(matrix).


You are passing a value. That value's type is a pointer.

> Isn't matrix by itself the first element address of matrix
> (&matrix[0][0]).Thanx again in advance.


No. It begins at the same address but its type is different.
matrix is of type int **
matrix[0] is of type int *
matrix[0][0] is of type int
&matrix[0][0] is of type int *

(void *)matrix == (void *)&matrix[0][0] is guaranteed to equal true
but that doesn't mean that they are the same thing. They aren't even
assignment-compatible.

You seem to bestow some magical properties on the fact that your
function parameter has a pointer type. You need to get rid of those.
It helps to think of the function parameter as a variable, like
"matrix" in your main() function.
Consider this code:
int **matrix;
int **matrix_backup;
matrix_backup = matrix;
matrix_backup = malloc(100 * sizeof(int *));
matrix[0] = malloc(100 * sizeof(int));
Assume (for the sake of simplicity) that malloc() always succeeds.
What do you think this sample code does, and why? The code you
submitted is doing the equivalent of this.

(snip)

--
/-- Joona Palaste (palaste@cc.helsinki.fi) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/
"Normal is what everyone else is, and you're not."
- Dr. Tolian Soran

10-06-2003 04:34 PM

Re: Still having trouble with malloc
 
matrix_backup is getting allocated memory for 100 int * and matrix[0] is
getting memory allocated for 100 int. But there is no relation between
matrix_backup and matrix. The matrix_backup = matrix is a redundant
statement. Am I correct? It still all fuzzy for me.

Joseph

"Joona I Palaste" <palaste@cc.helsinki.fi> wrote in message
news:bls48p$77m$1@oravannahka.helsinki.fi...
> raymis@hotmail.com scribbled the following:
> > I thought I was passing by pointer when I call the function

create(matrix).
>
> You are passing a value. That value's type is a pointer.
>
> > Isn't matrix by itself the first element address of matrix
> > (&matrix[0][0]).Thanx again in advance.

>
> No. It begins at the same address but its type is different.
> matrix is of type int **
> matrix[0] is of type int *
> matrix[0][0] is of type int
> &matrix[0][0] is of type int *
>
> (void *)matrix == (void *)&matrix[0][0] is guaranteed to equal true
> but that doesn't mean that they are the same thing. They aren't even
> assignment-compatible.
>
> You seem to bestow some magical properties on the fact that your
> function parameter has a pointer type. You need to get rid of those.
> It helps to think of the function parameter as a variable, like
> "matrix" in your main() function.
> Consider this code:
> int **matrix;
> int **matrix_backup;
> matrix_backup = matrix;
> matrix_backup = malloc(100 * sizeof(int *));
> matrix[0] = malloc(100 * sizeof(int));
> Assume (for the sake of simplicity) that malloc() always succeeds.
> What do you think this sample code does, and why? The code you
> submitted is doing the equivalent of this.
>
> (snip)
>
> --
> /-- Joona Palaste (palaste@cc.helsinki.fi) ---------------------------\
> | Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
> | http://www.helsinki.fi/~palaste W++ B OP+ |
> \----------------------------------------- Finland rules! ------------/
> "Normal is what everyone else is, and you're not."
> - Dr. Tolian Soran




Joona I Palaste 10-06-2003 05:00 PM

Re: Still having trouble with malloc
 
raymis@hotmail.com scribbled the following:
> matrix_backup is getting allocated memory for 100 int * and matrix[0] is
> getting memory allocated for 100 int. But there is no relation between
> matrix_backup and matrix. The matrix_backup = matrix is a redundant
> statement. Am I correct? It still all fuzzy for me.


You are sort of correct here. There is no inherent relation between
matrix and matrix_backup. So the operation matrix[0] = malloc(100 *
sizeof(int)) will cause undefined behaviour, since what has been
previously allocated is matrix_backup, not matrix.
Now the gist of the thing: Calling the create() function is doing the
same! The parameter "matrix" in the create() function is pretty much
like matrix_backup in the example code I posted. This is a crucial thing
to understand when writing C functions.

> Joseph


> "Joona I Palaste" <palaste@cc.helsinki.fi> wrote in message
> news:bls48p$77m$1@oravannahka.helsinki.fi...
>> raymis@hotmail.com scribbled the following:
>> > I thought I was passing by pointer when I call the function

> create(matrix).
>>
>> You are passing a value. That value's type is a pointer.
>>
>> > Isn't matrix by itself the first element address of matrix
>> > (&matrix[0][0]).Thanx again in advance.

>>
>> No. It begins at the same address but its type is different.
>> matrix is of type int **
>> matrix[0] is of type int *
>> matrix[0][0] is of type int
>> &matrix[0][0] is of type int *
>>
>> (void *)matrix == (void *)&matrix[0][0] is guaranteed to equal true
>> but that doesn't mean that they are the same thing. They aren't even
>> assignment-compatible.
>>
>> You seem to bestow some magical properties on the fact that your
>> function parameter has a pointer type. You need to get rid of those.
>> It helps to think of the function parameter as a variable, like
>> "matrix" in your main() function.
>> Consider this code:
>> int **matrix;
>> int **matrix_backup;
>> matrix_backup = matrix;
>> matrix_backup = malloc(100 * sizeof(int *));
>> matrix[0] = malloc(100 * sizeof(int));
>> Assume (for the sake of simplicity) that malloc() always succeeds.
>> What do you think this sample code does, and why? The code you
>> submitted is doing the equivalent of this.


--
/-- Joona Palaste (palaste@cc.helsinki.fi) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/
"The obvious mathematical breakthrough would be development of an easy way to
factor large prime numbers."
- Bill Gates

Nick Austin 10-06-2003 05:01 PM

Re: Still having trouble with malloc
 
On Mon, 06 Oct 2003 15:23:44 GMT, <raymis@hotmail.com> wrote:

>I fail to understand why that the memory allocated in the void
>create(int **matrix) does not remain. I passed the address of matrix so
>shouldn't it still have the allocated memory when it returns to main.
>The problem i am having is understanding why the printf statement in the
>code below gives the value. I would have expected it to be 123 which is
>the value I set it to in the create. Thanx in advance.
>
>void create(int **matrix);
>
>int main(void)
>{
>int **matrix;
>create(matrix);


First problem. This passes the value of an argument to the
function create. In this case it is an unitialised pointer
so its value is useless.

>printf("%d", matrix[1][1]); /* ? */


Second problem. The array dimensions of matrix are unknown
at this point. At the very least matrix needs to be defined
so that the second array dimension is known.

>}
>
>void create(int **matrix)
>{ /*allocating mem for 2 by 3 int matrix*/
>matrix = (int **)malloc(2*sizeof(int *));
>matrix[0] = (int *)malloc(3*sizeof(int));
>matrix[1] = (int *)malloc(3*sizeof(int));


This is also confused. It looks as though you are attempting
to create an array of two pointers each of which points to an
array of three ints.

>matrix[1][1] = 123;
>}


Personally I don't see the advantage of passing via a function
argument, so I'd rewrite it to use the return value instead:

#include <stdio.h>
#include <stdlib.h>

int (*create(void))[2][3];

int main(void)
{
int (*matrix)[][3];

matrix = create();

if ( matrix )
printf( "%d", (*matrix)[1][1] );
else
printf( "Cannot allocate memory\n" );
return 0;
}

int (*create(void))[2][3]
{
int (*matrix)[][3];

/*allocating mem for 2 by 3 int matrix*/
matrix = malloc( 2*3*sizeof(int) );

if ( matrix )
{
(*matrix)[1][1] = 123;
}
return matrix;
}

Nick.


Barry Schwarz 10-06-2003 11:30 PM

Re: Still having trouble with malloc
 
On Mon, 06 Oct 2003 18:01:00 +0100, Nick Austin
<nickDIGITONE@nildram.co.uk> wrote:

>On Mon, 06 Oct 2003 15:23:44 GMT, <raymis@hotmail.com> wrote:
>
>>I fail to understand why that the memory allocated in the void
>>create(int **matrix) does not remain. I passed the address of matrix so
>>shouldn't it still have the allocated memory when it returns to main.
>>The problem i am having is understanding why the printf statement in the
>>code below gives the value. I would have expected it to be 123 which is
>>the value I set it to in the create. Thanx in advance.
>>
>>void create(int **matrix);
>>
>>int main(void)
>>{
>>int **matrix;
>>create(matrix);

>
>First problem. This passes the value of an argument to the
>function create. In this case it is an unitialised pointer
>so its value is useless.


It is worse than useless. Passing an uninitialized value to a
function invokes undefined behavior.

>
>>printf("%d", matrix[1][1]); /* ? */

>
>Second problem. The array dimensions of matrix are unknown
>at this point. At the very least matrix needs to be defined
>so that the second array dimension is known.


Since matrix is not an array, it doesn't have dimensions and the
compiler doesn't need to know them. The successful evaluation of
matrix[1][1] requires only the following:
matrix point to an area properly aligned and having enough space
for two pointers to int.
matrix[1], which is the second pointer to int in the area
describe above, contain a value, actually the address, of an area
properly aligned and having enough space for two int.
matrix[1][1] contain a valid int value.

While it is not part of the OP's question, one of the potential
advantages of using an int** is that the dimension of each row can be
different, sometimes called a jagged matrix or jagged array.

snip


<<Remove the del for email>>


All times are GMT. The time now is 02:07 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.