Ошибка сегмента при заполнении массива Dynami c 2D - PullRequest
0 голосов
/ 31 марта 2020

Пока что в моей программе я динамически распределяю 4 матрицы (таким образом, что я могу получить доступ к элементу массива по arr [row] [col]), а затем заполняю их некоторыми значениями (позже для умножения на multi -threading). Программа принимает 3 дюйма, n, m и p. Матрица A - это n * m, B - это m * p, а C1 / C - это n * p. Проблема, с которой я сталкиваюсь, заключается в том, что некоторые входные данные вызывают ошибки сегмента, а другие нет. Например, ввод 4 4 4 прекрасно распределяет и заполняет слоты массива, но 5 5 5 дает мне ошибку сегмента при попытке доступа к элементу массива в части заполнения кода. Любая помощь будет принята с благодарностью.

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

Ответы [ 2 ]

0 голосов
/ 31 марта 2020

На самом деле есть несколько способов сделать это sh. Чтобы найти лучший способ и хорошее объяснение того, почему это лучший способ, вы можете прочитать это Правильное размещение многомерных массивов (спасибо Лундин)

Оповещение о спойлере, код в вопросе определенно не лучший способ go об этом по многим причинам, но короткая версия такова: при таком подходе это технически не 2d массив, а память разбросана по куче. Это создает проблемы при выполнении арифметики с указателями c, при использовании встроенных функций, таких как memcpy и многих других. Снова прочитайте стек выше для длинного и превосходного объяснения.

Тем не менее, если вы хотите сделать это по-своему, сначала вы должны malloc пространство для n раз размер указателя на int, так что A = malloc(n * sizeof(int*)), а затем для каждого i элемента, который вы можете выделить буфер, в m раз больше, чем int, так что A[i] = malloc(m * sizeof(int)). На самом деле, читая это, вы можете увидеть, как каждый mallo c оказывается в случайном месте в куче.

Возможно, эта таблица Ascii делает ее немного более понятной.

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]

Вы также можете представьте себе путь указателя, это также объясняет, почему вы используете указатель на указатель **A. Когда вы обращаетесь к элементу таким способом, вы делаете это:

*A указывает на первый элемент буфера int*, поэтому, если вы сделаете

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

, вышеприведенное получит вы адрес элемента A [0] [0] в памяти, и если вы будете следовать этому указателю, то есть

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

, вы фактически получите его значение.

0 голосов
/ 31 марта 2020

в двумерных массивах вы должны сначала выделить память для rows следующим образом:

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

затем выделить память для cols, как вы это сделали.

поскольку строка должна быть указателем на второе измерение массива.

, поэтому A = malloc(n * sizeof(int)); не является правильным, это должно быть A = malloc(n * sizeof(int*));, что означает, что вы выделяете память для указателя, а не целого числа.

...