malloc

Discussion in 'C Programming' started by Joseph, Oct 6, 2003.

  1. Joseph

    Joseph Guest

    I am trying to create a function that allocates memory for the matrix
    through a function; like the code below. However, this does not seem to
    work since I believe that the scope of the memory allocation only lasts
    within the create function. Is there anyway around this? Thanx in
    advance. I also DON'T want to declare int **matrix globally.


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

    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));
    }
    Joseph, Oct 6, 2003
    #1
    1. Advertising

  2. Joseph <> wrote:
    > I am trying to create a function that allocates memory for the matrix
    > through a function; like the code below. However, this does not seem to
    > work since I believe that the scope of the memory allocation only lasts
    > within the create function. Is there anyway around this? Thanx in
    > advance. I also DON'T want to declare int **matrix globally.



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


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


    malloc allocates space on the heap. variable declarations in the
    function allocate space on the stack. The stack goes away after
    the function, the heap stays. That was too easy, and I'm bored,
    so I'm going to rant...

    Ok... time to have some fun...

    (int *)malloc is redundant. The point of void * is that it matches
    anything.

    You could also statically allocate space on the stack inside your
    main since the program dies when main does.

    1) function pointers

    int **create(int x, int y, void *(*malloc)(size_t)){
    int i;
    int **retval = (malloc)(sizeof(int) * x);
    for(i = 0; i < y; i++)
    retval = (malloc)(sizeof(int) * y);
    return retval;
    }

    2) triple pointers

    int main( void ){
    int **matrix;
    create(42, 42, &matrix);
    }

    void create(int x, int y, int ***target){
    int i;
    *target = malloc(sizeof(int) * x);
    for(i = 0; i < y; i++)
    (*target) = (malloc)(sizeof(int) * y);
    }

    ok, time to get back to compilers...

    --
    Harrison Caudill | .^ www.hypersphere.org
    Computer Science & Physics Double Major | | Me*Me=1
    Georgia Institute of Technology | '/ I'm just a normal guy
    Charles Harrison Caudill, Oct 6, 2003
    #2
    1. Advertising

  3. I'm working on something similar, try the below,
    they are 1-D matrices e.g. a 4X4 matrix will be accessed like this:
    a[0], a[1], ... a[15].
    If you want I have other functions like print_matrix also.
    /*
    ** Generate a random matrix
    */
    double * gen_matrix(int numRows, int numCols, int initialize)
    {

    double *x = NULL;
    long i;

    x = (double*)calloc( (numRows*numCols), sizeof(double) );
    if(x == NULL) {
    exit(-1);
    }

    /* initialize to zero */
    if(!initialize) {
    for(i = 0; i < numRows*numCols; i++) {
    x = 0.0;
    /*printf("%d %g\n", i, x);*/
    }
    }
    else {
    /* seed rand() with time so it starts randomly */
    srand( (unsigned)time(NULL) );

    for(i = 0; i < numRows*numCols; i++) {
    x = i;
    /*printf("%d %g\n", i, x);*/
    }
    }

    return x;

    }

    int main(int argc, char **argv)
    {

    double *a = NULL;
    double *b = NULL;
    double *c = NULL;
    /* other code */
    a = gen_matrix(numRowsA, numColsA, 1);
    b = gen_matrix(numRowsB, numColsB, 1);
    c = gen_matrix(numRowsA, numColsB, 0);
    ....
    free(a);
    free(b);
    free(c);

    }





    Joseph wrote:
    > I am trying to create a function that allocates memory for the matrix
    > through a function; like the code below. However, this does not seem to
    > work since I believe that the scope of the memory allocation only lasts
    > within the create function. Is there anyway around this? Thanx in
    > advance. I also DON'T want to declare int **matrix globally.
    >
    >
    > int main(void)
    > {
    > int **matrix;
    > create(matrix);
    > }
    >
    > 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));
    > }
    >
    Pushkar Pradhan, Oct 6, 2003
    #3
  4. "Joseph" <> schrieb im Newsbeitrag
    news:VU7gb.118421$...
    > I am trying to create a function that allocates memory for the matrix
    > through a function; like the code below. However, this does not seem to
    > work since I believe that the scope of the memory allocation only lasts
    > within the create function. Is there anyway around this? Thanx in
    > advance. I also DON'T want to declare int **matrix globally.
    >
    >
    > int main(void)
    > {
    > int **matrix;
    > create(matrix);
    > }
    >
    > 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));
    > }


    For sure not the best solution, but the experts here will point out what's
    flawed :)

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

    #define NUM_ROWS 2
    #define NUM_COLS 3

    int **destroy(int **matrix, int rows)
    {
    int i;
    for(i = 0; i < rows; i++)
    {
    free(matrix);
    }
    free(matrix);
    matrix = NULL;
    return matrix;
    }

    int ** create(int rows, int cols)
    {
    int **matrix;
    int i;
    int alloc_success = 1;

    matrix = malloc(rows * sizeof *matrix);
    if(matrix)
    {
    for(i = 0; i < rows; i++)
    {
    matrix = malloc(cols * sizeof **matrix);
    if(!matrix)
    {
    alloc_success = 0;
    }
    }
    if(!alloc_success)
    {
    matrix = destroy(matrix, rows);
    }
    }

    return matrix;
    }



    int main(void)
    {
    int i;
    int j;
    int **matrix = create(NUM_ROWS, NUM_COLS);

    /*use matrix*/
    if(matrix)
    {
    for(i = 0; i < NUM_ROWS; i++)
    {
    for(j = 0; j < NUM_COLS; j++)
    {
    matrix[j] = i * NUM_COLS + j;
    printf("%d\n", matrix[j]);
    }
    }
    /*cleanup*/
    destroy(matrix, NUM_ROWS);
    return EXIT_SUCCESS;
    }
    return EXIT_FAILURE;
    }

    Robert
    Robert Stankowic, Oct 6, 2003
    #4
  5. Joseph

    Martijn Guest

    Pushkar Pradhan wrote:
    > I'm working on something similar, try the below,
    > they are 1-D matrices e.g. a 4X4 matrix will be accessed like this:
    > a[0], a[1], ... a[15].
    > If you want I have other functions like print_matrix also.
    > /*
    > ** Generate a random matrix
    > */
    > double * gen_matrix(int numRows, int numCols, int initialize)
    > {
    >
    > double *x = NULL;
    > long i;
    >
    > x = (double*)calloc( (numRows*numCols), sizeof(double) );
    > if(x == NULL) {
    > exit(-1);
    > }
    >


    why do you use calloc if you initialize it right after, anyway?

    > /* initialize to zero */
    > if(!initialize) {
    > for(i = 0; i < numRows*numCols; i++) {
    > x = 0.0;
    > /*printf("%d %g\n", i, x);*/
    > }
    > }
    > else {
    > /* seed rand() with time so it starts randomly */
    > srand( (unsigned)time(NULL) );
    >
    > for(i = 0; i < numRows*numCols; i++) {
    > x = i;
    > /*printf("%d %g\n", i, x);*/
    > }
    > }
    >
    > return x;
    >
    > }


    You could also have some fun and make a matrix type:

    struct matrix
    {
    double* content;
    unsigned int cols;
    }

    gen_matrix would be (I made it a litte more flexible, so it wouldn't exit on
    failure):

    struct matrix* gen_matrix(unsigned int rows, unsigned int cols)
    {
    struct matrix *matrix_ptr;

    matrix_ptr = malloc(sizeof *matrix_ptr);
    if ( matrix_ptr == NULL )
    return ( NULL );

    matrix_ptr->content = malloc(sizeof *matrix_ptr->content * rows *
    cols);
    if ( matrix_ptr->content == NULL )
    {
    free(matrix_ptr);
    return ( NULL );
    }

    /* do any initialization of the content */

    matrix_ptr->cols = cols;

    return ( matrix_ptr );
    }

    Of course you could include the type it creates in both the name of the
    structure and function (double vs int).

    Now it is easier to use the indexes with getters and setters (uses 1-base
    indexing, btw):

    double get_matrix_value(struct matrix *matrix_ptr, unsigned int row,
    unsigned int col)
    {
    if ( row == 0 || col == 0 )
    return ( 0.0 ); /* set an error here */

    return ( matrix_ptr->content[matrix_ptr->cols * (row - 1) + (col -
    1)] );
    }

    Of course I don't check on out of bounds, so you would have to tweak this to
    your needs (e.g. add the rows property to the structure as well, and check
    for overflow).

    Hope this helps,

    --
    Martijn
    http://www.sereneconcepts.nl
    Martijn, Oct 6, 2003
    #5
  6. Joseph

    Mike Wahler Guest

    "Joseph" <> wrote in message
    news:VU7gb.118421$...
    > I am trying to create a function that allocates memory for the matrix
    > through a function; like the code below. However, this does not seem to >

    work since I believe that the scope of the memory allocation only lasts >
    within the create function. Is there anyway around this? Thanx in
    > advance. I also DON'T want to declare int **matrix globally.
    >
    >
    > int main(void)
    > {
    > int **matrix;
    > create(matrix);
    > }
    >
    > 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));
    > }


    It's always a good idea to search past messages,
    very likely your question has already been asked
    and answered. From one of my recent posts (Sep 26):


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

    double **alloc2d(size_t rows, size_t cols)
    {
    double **result;
    size_t row = 0;
    size_t col = 0;

    if(result = malloc(rows * sizeof *result))
    {
    if(*result = malloc(rows * cols * sizeof **result))
    for(row = 1; row < rows; ++row)
    result[row] = *result + row * cols;
    else
    {
    free(result);
    result = NULL;
    }
    }

    return result;
    }

    void release2d(double **arr)
    {
    free(*arr);
    free(arr);
    }

    void populate2d(double **arr, size_t rows, size_t cols)
    {
    size_t row = 0;
    size_t col = 0;

    for(row = 0; row < rows; ++row)
    for(col = 0; col < cols; ++col)
    arr[row][col] = row * cols + col;
    }

    void show2d(double **arr, size_t rows, size_t cols)
    {
    size_t row = 0;
    size_t col = 0;

    for(row = 0; row < rows; ++row)
    {
    for(col = 0; col < cols; ++col)
    printf("%4.0f", arr[row][col]);

    putchar('\n');
    }
    }

    int main()
    {
    size_t rows = 10;
    size_t cols = 10;
    size_t row = 0;
    size_t col = 0;
    double **arr = NULL;
    const int retcodes[] = {EXIT_FAILURE, EXIT_SUCCESS};
    int status = 0;

    if(status = (arr = alloc2d(rows, cols)) != NULL)
    {
    populate2d(arr, rows, cols);
    show2d(arr, rows, cols);
    release2d(arr);
    }

    printf("%s\n", status ? "" : "Cannot allocate memory");
    return retcodes[status];
    }

    HTH,
    -Mike
    Mike Wahler, Oct 6, 2003
    #6
  7. Joseph

    Joseph Guest

    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;
    }
    Joseph, Oct 6, 2003
    #7
  8. On Mon, 06 Oct 2003 06:24:53 GMT, Joseph <> wrote:

    >I am trying to create a function that allocates memory for the matrix
    >through a function; like the code below. However, this does not seem to
    >work since I believe that the scope of the memory allocation only lasts
    >within the create function. Is there anyway around this? Thanx in
    >advance. I also DON'T want to declare int **matrix globally.
    >
    >
    >int main(void)
    >{
    > int **matrix;
    > create(matrix);


    Problems here:

    matrix is uninitialized. Passing an uninitialized value to a
    function (or any attempt to evaluate an uninitialized value) invokes
    undefined behavior.

    There is no way for the function to return the value/address of
    the matrix it creates. Remember that c passes by value so that
    whatever the function does to matrix actually happens to a copy of
    matrix that is lost when the function returns.

    There is no prototype in scope for create.

    >}


    The solution to the prototype problem is obvious

    There are two popular solutions to the other problems:

    Since you only want to return one value, define the function to
    do just that, as with the prototype
    int** create(void);
    Your function call the function with something like
    matrix = create();
    and the function would then look like
    int** create(void){
    int **ptr, i;
    ptr = malloc(N * sizeof *ptr);
    if (ptr == NULL){/* error handling */}
    for (i = 0; i < M; i++){
    ptr = malloc(N * sizeof *ptr);
    if (ptr == NULL){/* error handling */}
    }
    return ptr;
    }

    If you really want the value returned in a variable, pass the
    address of that variable to the function which can then dereference
    the address and update the variable directly. The prototype would
    look like
    void create(int***);
    The call would look like
    create(&matrix);
    and the function would look like
    void create (int ***ptr){
    int i;
    *ptr = malloc(N * sizeof **ptr);
    if ...
    for (i = 0; i < M; i++){
    (*ptr) = malloc(M * sizeof *(*ptr));
    if ...
    }
    }

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


    While you are at it, NEVER cast the return from malloc. It can never
    help but it can suppress compiler diagnostics you want to see.

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




    <<Remove the del for email>>
    Barry Schwarz, Oct 6, 2003
    #8
  9. Re: still having trouble with malloc

    "Joseph" <> schrieb im Newsbeitrag
    news:RHfgb.123896$...
    > 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);


    Here you pass a _copy_ of matrix. In create() you request (and hopefully
    get, because you don't check the return value of malloc() for NULL) some
    memory and assign the pointer malloc() returns to the _copy_ of matrix. This
    _does not_ change the value of the original matrix in main(). So as soon as
    you return from create() the requested memory is still there, but you lost
    the pointer to it and therefore you have absolutely no way to access it.
    there are two ways out:
    1) look at my example I posted elsethread
    2) pass a _pointer_ to matrix to create() like in

    create(&matrix);

    Now create gets the _address_ of the pointer and thus can modify the
    **matrix in main()
    (see below)

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


    This must be
    void create(int ***ptr_to_matrix)

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


    *ptr_to_matrix = (int **)malloc(2*sizeof(int *));
    or better
    #include <stdlib.h> before your actual code and get rid of the cast and use
    the preferred way of using the sizeof, which makes the statement remain
    correct even if you change the type of **matrix:

    *ptr_to_matrix = malloc(2 * sizeof **ptr_to_matrix);
    ......

    (*ptr_to_matrix)[0] = malloc(3 * sizeof ***ptr_to_matrix);

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


    I personally _hate_ more than two levels of indirection, so I prefer to
    return a pointer to the allocated memory and assign the returned pointr to
    the original in the calling functions (see my example elsethread).

    Please look at the examples given in our answers for better solutions and
    proper error checking
    HTH
    Robert
    Robert Stankowic, Oct 6, 2003
    #9
  10. Joseph

    Al Bowers Guest

    Joseph wrote:
    > I am trying to create a function that allocates memory for the matrix
    > through a function; like the code below. However, this does not seem to
    > work since I believe that the scope of the memory allocation only lasts
    > within the create function. Is there anyway around this? Thanx in
    > advance. I also DON'T want to declare int **matrix globally.
    >
    >
    > int main(void)
    > {
    > int **matrix;
    > create(matrix);
    > }
    >
    > 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));
    > }
    >


    The parameter matrix in function create is passed by value. A copy
    is made and used in the function. It is changed with the malloc call.
    But since it is a copy, matrix in function main remains unchanged.
    To correct this and also add some safety and functionality make the
    prototype:

    int create(int ***matrix):

    the definition and test code:

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

    int create(int ***matrix)
    {
    *matrix = malloc(2*(sizeof **matrix));
    if(*matrix == NULL) return 0;
    if(((*matrix)[0] = malloc(3*(sizeof ***matrix))) == NULL)
    {
    free(*matrix);
    return 0;
    }
    if(((*matrix)[1] = malloc(3*(sizeof ***matrix))) == NULL)
    {
    free((*matrix)[0]);
    free(*matrix);
    return 0;
    }
    /* test */
    (*matrix)[1][1] = 122;
    return 1;
    }

    int main(void)
    {
    int **matrix;
    if(create(&matrix))
    printf("matrix[1][1] = %d\n",matrix[1][1]);
    /* TODO Write code on free the dymanic allocations */
    return 0;
    }

    --
    Al Bowers
    Tampa, Fl USA
    mailto: (remove the x)
    http://www.geocities.com/abowers822/
    Al Bowers, Oct 6, 2003
    #10
  11. Joseph

    cody Guest

    try that (not tested):

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

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

    --
    cody

    [Freeware, Games and Humor]
    www.deutronium.de.vu || www.deutronium.tk
    cody, Oct 10, 2003
    #11
  12. Joseph

    NumLockOff Guest

    "cody" <> wrote in message
    news:bm4sje$io57f$-berlin.de...
    > try that (not tested):
    >
    > int main(void)
    > {
    > int **matrix;
    > create(matrix);


    create (&matrix);

    sounds better..

    > }
    >
    > 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));
    > }
    >
    > --
    > cody
    >
    > [Freeware, Games and Humor]
    > www.deutronium.de.vu || www.deutronium.tk
    >
    >
    NumLockOff, Oct 10, 2003
    #12
  13. Joseph

    Dan Pop Guest

    In <bm4sje$io57f$-berlin.de> "cody" <> writes:

    >try that (not tested):
    >
    > int main(void)
    > {
    > int **matrix;
    > create(matrix);


    Undefined behaviour: you're implicitly declaring create() as function
    returning int. You're also passing create() an uninitialised pointer of
    the wrong type.

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


    Undefined behaviour: you're implicitly declaring malloc as a function
    returning int. Due to the bogus cast, the compiler is not even required
    to diagnose the bug.

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


    Could you, please, consider learning C *before* continuing to post in this
    newsgroup?

    Dan
    --
    Dan Pop
    DESY Zeuthen, RZ group
    Email:
    Dan Pop, Oct 10, 2003
    #13
  14. Joseph

    cody Guest

    > Could you, please, consider learning C *before* continuing to post in this
    > newsgroup?


    ok iam so sorry, as i said my code was untested. at least i tried to help.

    --
    cody

    [Freeware, Games and Humor]
    www.deutronium.de.vu || www.deutronium.tk
    cody, Oct 10, 2003
    #14
  15. Joseph

    Dan Pop Guest

    In <bm6c9u$j65bo$-berlin.de> "cody" <> writes:

    >> Could you, please, consider learning C *before* continuing to post in this
    >> newsgroup?

    >
    >ok iam so sorry, as i said my code was untested. at least i tried to help.


    I can't see how such a thoroughly broken piece of code could help anyone.
    First, learn C yourself and *only* then try to help other people. Tested
    or not, your code clearly demonstrates your incompetence on C programming
    issues.

    Dan
    --
    Dan Pop
    DESY Zeuthen, RZ group
    Email:
    Dan Pop, Oct 10, 2003
    #15
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John
    Replies:
    13
    Views:
    699
  2. ravi
    Replies:
    0
    Views:
    450
  3. Peter
    Replies:
    34
    Views:
    1,936
    Richard Tobin
    Oct 22, 2004
  4. porting non-malloc code to malloc

    , Feb 18, 2005, in forum: C Programming
    Replies:
    3
    Views:
    479
    Walter Roberson
    Feb 19, 2005
  5. Johs32

    to malloc or not to malloc??

    Johs32, Mar 30, 2006, in forum: C Programming
    Replies:
    4
    Views:
    320
    Captain Winston
    Mar 30, 2006
Loading...

Share This Page