简体   繁体   中英

Seg fault when filling in dynamic 2d array

So far in my program, I am dynamically allocating 4 matrices (in a way such that I can access an array member by arr[row][col]) and then filling them with some values (later to be multiplied with multi-threading). The program takes in 3 ints, n, m and p. Matrix A is n * m, B is m * p and C1/C are n * p. The problem I'm running into is that some inputs cause seg faults while others don't. For example, input 4 4 4 allocates and fills the array slots perfectly fine, but 5 5 5 gives me a seg fault when trying to access an array member in the fill portion of the code. Any help would be greatly appreciated.

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

int **A;
int **B;
int **C1;
int **C;

void allocateMatrices(int n, int m, int p) {
    int i, j;

    /* Allocate n * m array */
    A = malloc(n * sizeof(int));
    for (i = 0; i < n; i++) {
        A[i] = malloc(m * sizeof(int));
    }

    /* Allocate m * p array */
    B = malloc(m * sizeof(int));
    for (i = 0; i < m; i++) {
        B[i] = malloc(p * sizeof(int));
    }

    /* Allocate two n * p arrays */
    C1 = malloc(n * sizeof(int));
    C = malloc(n * sizeof(int));
    for (i = 0; i < n; i++) {
        C[i] = malloc(p * sizeof(int));
        C1[i] = malloc(p * sizeof(int));
    }

    /* Fill matrix A */
    for (i = 0; i < n; i++) {
        for (j = 0; j < m; j++) {
            A[i][j] = i * j;
        }
    }

    /* Fill matrix B */
    for (i = 0; i < m; i++) {
        for (j = 0; j < p; j++) {
            B[i][j] = i + j;
        }
    }
}

int main() {
    int n, m, p;
    printf("Enter n (<=6000), m (<=3000), p (<=1000): ");
    scanf("%d %d %d", &n, &m, &p);

    allocateMatrices(n, m, p);
}

in 2D arrays you should first allocate memory for rows like this:

row=malloc(number * sizeof(int *))

then allocate memory for cols like you did.

because row should be a pointer to second dimension of array.

so A = malloc(n * sizeof(int)); is not right , this should be A = malloc(n * sizeof(int*)); which means you are allocating memory for a pointer not a integer.

There's actually a couple ways you can accomplish this. For the best way and a good explanation on why it's the best way you can read this Correctly allocating multi-dimensional arrays (thanks Lundin)

Spoiler alert, the code in the question is definitely not the best way to go about this for numerous reasons, but the short version is this: with this approach it's technically not a 2d array and the memory is scattered over the heap. That gives you trouble when doing pointer arithmetic, using built in functions like memcpy and many more. Again read the stack above for the long and excellent explanation.

Nonetheless, if you want to do it your way, you first have to malloc the space for n times the size of pointer to int, so A = malloc(n * sizeof(int*)) and then for every i element of that you can allocate a buffer with m times the size of int, so A[i] = malloc(m * sizeof(int)) . Actually reading this you can see how every malloc ends up in a random space on the heap.

Maybe this Ascii table makes it a little clearer.

A[i]     A[0]  A[1]  A[2]  A[3]  A[4] A[...]

*A   -> [int*, int*, int*, int*, int*, ...]
          |     |     |     |     |     |
          v     v     v     v     v     v                
         ____  ____  ____  ____  ____  ____
A[i][1] |int ||int ||int ||int ||int ||... |
A[i][2] |int ||int ||int ||int ||int ||... |
A[i][3] |int ||int ||int ||int ||int ||... |
A[i][4] |int ||int ||int ||int ||int ||... |
...     |... ||... ||... ||... ||... ||... |

A has the address of A[0], so A == &A[0]
*A gives the value of A[0], so *A == A[0]
A[0] has the address of A[0][0], so A[0] == &A[0][0]
*A[0] gives the value of A[0][0], so *A[0] == A[0][0]
**A is the same as A[0][0], so **A == A[0][0]

You can also picture it the pointer way, this also explains why you use a pointer to a pointer **A . When you access an element this way you would do this:

*A points to the first element of a buffer of int* so if you do

printf("This is the address of the int A[0][0]: %p\n", *A);

the above would get you the address of the element A[0][0] in memory and if you follow that pointer, ie

printf("This is the value of the int A[0][0]: %d\n", **A);

you actually get it's value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM