Ошибка сегментирования (образ памяти сброшен на диск)

Я функции для выделения памяти под матрицу размером NxM, освобождения памяти от матрицы, заполнения матрицы по формуле, но выводит ошибку сегментации, можете помочь с решением проблемы

функция main():

int main() {
    srand(time(NULL));
    //объявляем переиеные и заполняем их случайными числами
    int N, M, precision;
    N = rand() % 8 + 8;
    M = rand() % 8 + 8;
    precision = rand() % 6 + 3;
    //создаёт матрицу
    double **A = start(N, M);
    printf("N: %d\nM: %d\n", N, M);
    //start(&A, N, M);
    printf("%ld\n", sizeof(A));
    //заполняем матрицу с помощью формулы
    sapol(&A, 7, 8);
    //выводим матрицу на экране
    for(int i = 0; i< 7; ++i){
        for (int j = 0; j< 8; ++j){
            printf("%lf ", A[i][j]);
        }
        putchar('\n');
    }
    return 0;
}

функции по матрице:

//создаёт матрицу размером NxM
void* start(int N, int M) {
    double **A = (double**)malloc(N * sizeof(double*));
    if (A == NULL) printf("ERROR: Не удалось выделить память под матрицу\n"); 
    for (int i = 0; i< N; ++i){
        *(A+i) = (double*)malloc(M * sizeof(double));
        //if (A == NULL) printf("ERROR: Не удалось выделить память под строку матрицы\n");
    }
    return A;
}
//освобождает память под матрицу
void* free_all(double **A, int N){
    for (int i = 0; i < N; ++i)
        free(A[i]);
    return A;
}
//функция фактариала
double factorial(int n){
    long double s = 0;
    for (int i = 1; i <= n; ++i){
        s *= i;
    }
    return s;
}
//заполняет матрицу по формуле
void sapol(double ***A, int N, int M){
    for (int i = 0; i < N; ++i){
        for (int j = 0; j < M; ++j){
            if (i == j) ***(A+i*M+j) = 1.0;
            else
                ***(A+i*M+j) = (i>j) ?  1.0/ pow(factorial((double) j), (double) i) : pow(-1.0, (double) i) / pow(factorial((double) j), (double) i);
        }
    }
}

вывод в консоли:

код ошибки


Ответы (1 шт):

Автор решения: Stanislav Volodarskiy

у вас программе смешан код для двух разных представлений матрицы. Выделяете вы её как массив массивов (double **), а обращаетсь как к упакованной матрице (A+i*M+j). Так нельзя.

double **

Если вы решили хранить матрицу в массиве массивов, то все операции парами: два malloc, два free, два разыменования указателя:

что как
тип item_type **
выделение malloc, malloc
удаление free, free
обращение к элементу a[i][j]
#include <stdio.h>
#include <stdlib.h>

void release(int n, double **a) {
    for (int i = 0; i < n; ++i) {
        free(a[i]);
    }
    free(a);
}

double **allocate(int n, int m) {
    double **a = malloc((size_t)n * sizeof(*a));
    if (n > 0 && a == NULL) {
        return NULL;
    }
    for (int i = 0; i < n; ++i) {
        a[i] = malloc((size_t)m * sizeof(**a));
        if (m > 0 && a[i] == NULL) {
            release(i, a);
            return NULL;
        }
    }
    return a;
}

void fill(int n, int m, double **a) {
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            a[i][j] = i + 0.001 * j;
        }
    }
}

void print(int n, int m, double **a) {
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            if (j > 0) {
                putchar(' ');
            }
            printf("%7.3lf", a[i][j]);
        }
        puts("");
    }
}

int main() {
    int n, m;
    if (scanf("%d%d", &n, &m) != 2) {
        exit(1);
    }

    double **a = allocate(n, m);
    if (n > 0 && a == NULL) {
        exit(1);
    }
    
    fill(n, m, a);
    print(n, m, a);
    release(n, a);
}

double *

Если вы решили хранить матрицу в одном массиве, в котором строки лежат друг за другом, то все действия под одному:

что как
тип item_type *
выделение malloc
удаление free
обращение к элементу a[m * i + j]
#include <stdio.h>
#include <stdlib.h>

double *allocate(int n, int m) {
    double *a = malloc((size_t)(n * m) * sizeof(*a));
    if (n > 0 && m > 0 && a == NULL) {
        return NULL;
    }
    return a;
}

void fill(int n, int m, double *a) {
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            a[m * i + j] = i + 0.001 * j;
        }
    }
}

void print(int n, int m, double *a) {
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            if (j > 0) {
                putchar(' ');
            }
            printf("%7.3lf", a[m * i + j]);
        }
        puts("");
    }
}

int main() {
    int n, m;
    if (scanf("%d%d", &n, &m) != 2) {
        exit(1);
    }

    double *a = allocate(n, m);
    if (n > 0 && m > 0 && a == NULL) {
        exit(1);
    }
    
    fill(n, m, a);
    print(n, m, a);
    free(a);
}
→ Ссылка