0

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);
}
almosthavoc
  • 159
  • 10
  • 2
    `A = malloc(n * sizeof(int));` should be `A = malloc(n * sizeof(int*));` (or perhaps even better would be `A = malloc(n * sizeof(*A));`) - the same happens with your allocations of `B`, `C` and `C1` – UnholySheep Mar 31 '20 at 07:25
  • @UnholySheep Yup, that would do it. Thank you! – almosthavoc Mar 31 '20 at 07:29
  • In this case you should forget about pointer-to-pointer and [Correctly allocating multi-dimensional arrays](https://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays) instead, so that you get 2D arrays instead of look-up tables. – Lundin Mar 31 '20 at 09:36

2 Answers2

0

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.

hanie
  • 1,863
  • 3
  • 9
  • 19
0

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, i.e.

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

you actually get it's value.

wschopohl
  • 1,567
  • 1
  • 11
  • 18
  • 1
    This picture explains exactly why the allocated memory is _not_ a 2D array. That geek site is, as always, crap and some of the examples there are very fishy. – Lundin Mar 31 '20 at 09:38
  • Can you elaborate a bit more? Do you mean the result doesn't have to be a 2d array because it's one buffer pointing to multiple other buffers that all could be of different length? But used as in the example you actually do get something that's very much behaving like a 2d array, don't you? Also do you habe a better reference site? I know the geek site is not the best, but at least the 3 examples they give are the ones that came to my mind and they all seem to work.. Thanks for your feedback! – wschopohl Mar 31 '20 at 13:07
  • https://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays Better reference site: https://stackoverflow.com/ :) – Lundin Mar 31 '20 at 13:16
  • thanks, I tried to improve my answer and gave you credit. I knew I should have never tried to answer that question :D – wschopohl Mar 31 '20 at 16:12
  • 1
    No worries, the answer is not wrong apart from this data type not being a 2D array. The pointer-to-pointer technique has its place too, when you need things like an array of strings etc. Just not when you actually want an `int [x][y]` 2D array or similar. – Lundin Apr 01 '20 at 06:54