malloc-ating multidimensional array in function

前端 未结 7 1810
傲寒
傲寒 2020-12-10 22:28

I\'m trying to allocate a 2d array in a C program. It works fine in the main function like this (as explained here):

#include 
#include 

        
相关标签:
7条回答
  • 2020-12-10 22:58

    That is not a multidimensional array; it is a single dimensional array containing pointers to single dimensional arrays. Multidimensional arrays do not contain pointers; they are single memory blocks.

    Your problem here is that you have a pointer to a pointer, and you're trying to return it from your function through a parameter. If you're going to do that, you're going to need a pointer to a pointer to a pointer as your parameter, and you're going to have to pass the address of a pointer to a pointer to the method. If you don't do this, you're not changing the value of the variable grid in main -- you're changing the one which was copied as the parameter to the malloc2d function. Because the grid in main is left uninitialized, you get a undefined behavior.

    Here's an example of what I mean as the fix:

    #include <stdio.h>
    #include <stdlib.h>
    
    int malloc2d(int *** grid, int nrows, int ncols){
        int i;
        *grid = malloc( sizeof(int *) * nrows);
    
        if (*grid == NULL){
            printf("ERROR: out of memory\n");
            return 1;
        }
    
        for (i=0;i<nrows;i++){
            (*grid)[i] = malloc( sizeof(int) * ncols);
            if ((*grid)[i] == NULL){
                printf("ERROR: out of memory\n");
                return 1;
            }
        }
        printf("Allocated!\n");
        return 0;
    }
    
    int main(int argc, char ** argv)
    {
        int ** grid;
    
        malloc2d(&grid, 10, 10);
        grid[5][6] = 15;
        printf("%d\n", grid[5][6]);
        return 0;
    }
    

    Additional notes:

    • If a single allocation fails, you leak the allocation for the first array, as well as the allocations for all previous rows. You need to call free on those before returning.
    • You're returning through a parameter, even though you really don't have to. If I were writing this, I'd make the method return int **, and signal error by returning 0.
    0 讨论(0)
  • 2020-12-10 23:03

    C is pass by value. And to sum up the error you are doing, this example should be helpful -

    void foo( int *temp )
    {
         temp = malloc(sizeof(int)) ;
         // temp is assigned to point to new location but the actual variable
         // passed from main do not point to the location temp is pointing to.
    
         *temp = 10 ;
    }
    
    int main()
    {
         int *ptr ;
         foo( ptr ) ;
    
         // ptr is still unintialized
         *ptr = 5 ; // Segmentation fault or Undefined behavior
    
         return 0;
    }
    

    So, instead you should do -

    void foo( int **temp )
    {
        *temp = malloc(sizeof (int) );
        // ...
    }
    

    And now call the function as foo(&ptr); in the main() function.

    0 讨论(0)
  • 2020-12-10 23:03

    If you still want malloc2d to return a status code, the parameter needs to be of type int***:

    int malloc2d(int *** grid, int nrows, int ncols){
    

    And you need to use *grid to refer to the supplied buffer:

        int i;
        *grid = malloc( sizeof(int *) * nrows);
    
        if (*grid == NULL){
            printf("ERROR: out of memory\n");
            return 1;
        }
    
        for (i=0;i<nrows;i++){
            (*grid)[i] = malloc( sizeof(int) * ncols);
            if ((*grid)[i] == NULL){
                printf("ERROR: out of memory\n");
                return 1;
            }
        }
        printf("Allocated!\n");
        return 0;
    }
    

    Then, when calling malloc2d, pass it the address of an int** to fill in:

    int ** grid;
    
    malloc2d(&grid, 10, 10);
    
    0 讨论(0)
  • 2020-12-10 23:06

    Shorter should be below, with free (!) and initialized values for each grid element:

    #include <stdio.h>
    #include <stdlib.h>
    
    #define NROWS 10
    #define NCOLS 10
    
    int main()
    {
        int (* grid)[NCOLS] = calloc(NROWS,sizeof*grid);
    
        /* no more needed here malloc2d(grid, 10, 10); */
        grid[5][6] = 15;
        printf("%d\n", grid[5][6]);
        free(grid); /* every c/malloc need a free */
        return 0;
    }
    
    0 讨论(0)
  • 2020-12-10 23:11

    C is actually always pass by value, so when you pass in 'grid' you are passing in a value and the function is modifying its own local copy. Try passing in '&grid' instead and modify malloc2d appropriately.

    0 讨论(0)
  • 2020-12-10 23:19

    That's not your about your segmentation fault problem, but you should really consider to use a single malloc call to allocate all necessary memory space need by grid.

    grid = malloc (nrows * ncols * sizeof(int *))
    

    Look at Bill ONeary answer regarding pointer of pointer of pointer.

    0 讨论(0)
提交回复
热议问题