我想写一个简单的C程序来接收矩阵(首先是它的大小)并求反它,所以我写了一些代码,编译它,运行并得到一个‘Malloc:Corrupt top Size’的错误,对于大小大于2的矩阵.我判断了代码中是否有未释放的内存,但我就是看不出哪里搞错了.

代码本身:

#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

double det(double **matrix, int n, int m);
int invert(double **matrix, int n, int m);

int input(double ***matrix, int *n, int *m);
void output(double **matrix, int n, int m);

double **allocate_matrix(int n, int m);

int main(void) {
    double **matrix;
    int n, m;
    if (input(&matrix, &n, &m) == 0 && invert(matrix, n, m) == 0) {
        output(matrix, n, m);
        free(matrix);
    } else
        printf("n/a");
    return 0;
}

// Secondary functions

void swap(void *a, void *b, size_t size) {
    void *c = malloc(size);
    memcpy(c, a, size);
    memcpy(a, b, size);
    memcpy(b, c, size);
    free(c);
}

// Matrix allocation

double **allocate_matrix(int n, int m) {
    double **matrix = malloc(n * m * sizeof(double) + n * sizeof(double *));
    double *data = (double *)(matrix + n);
    for (int i = 0; i < n; i++) matrix[i] = data + m * i;
    for (int i = 0; i < n * m; i++) data[i] = 0;
    return matrix;
}

// Matrix operations

void matrix_for_det(double **matrix, int n, int m, double **res, int y, int x) {
    int in = 0, jn = 0;
    for (int i = 0; i < n; i++) {
        if (i == y) continue;
        for (int j = 0; j < m; j++) {
            if (j == x) continue;
            res[in][jn] = matrix[i][j];
            jn++;
        }
        in++;
    }
}

void matrix_const_mul(double **matrix, int n, int m, double c) {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            matrix[i][j] *= c;
        }
    }
}

double det(double **matrix, int n, int m) {
    if (n != m) return NAN;
    if (n == 2) return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix [1][0];
    if(n == 1) return matrix[0][0];
    double result = 0;
    double **next = allocate_matrix(n - 1, m - 1);
    if (next != NULL) {
        for (int col = 0; col < m; col++) {
            matrix_for_det(matrix, n, m, next, 0, col);
            double atom = matrix[0][col] * det(next, n - 1, m - 1);
            if (col % 2 == 0)
                result += atom;
            else
                result -= atom;
        }
        free(next);
    } else
        result = NAN;
    return result;
}

int transpose(double ***matrix, int *n, int *m) {
    int exit_status = 0;
    double **result = allocate_matrix(*m, *n);
    if (result != NULL) {
        for (int i = 0; i < *n; i++) {
            for (int j = 0; j < *m; j++) {
                result[j][i] = (*matrix)[i][j];
            }
        }
        free(*matrix);
        *matrix = result;
        swap(n, m, sizeof(int));
    } else
        exit_status = -1;
    return exit_status;
}

int invert(double **matrix, int n, int m) {
    int exit_status = 0;
    double **new = allocate_matrix(n, m);
    double **next = allocate_matrix(n - 1, m - 1);
    if (new != NULL && next != NULL) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                matrix_for_det(matrix, n, m, next, i, j);
                new[i][j] = det(next, n - 1, m - 1);
                if ((i + j) % 2 == 1) new[i][j] *= -1;
            }
        }
        free(next);

        if (transpose(&new, &n, &m) == 0) {
            double det_v = det(matrix, n, m);
            matrix_const_mul(new, n, m, 1. / det_v);

            memcpy(matrix[0], new[0], n * m * sizeof(double));
        } else
            exit_status = -1;

        free(new);
    } else {
        if (new) free(new);
        if (next) free(next);
    }
    return exit_status;
}

// Input Output

int check_string() {
    int exit_status = 0;
    int c;
    while ((c = getchar()) != EOF && c != '\n' && exit_status == 0) {
        if (!isspace(c)) exit_status = -1;
    }
    return exit_status;
}

int input(double ***matrix, int *n, int *m) {
    int exit_status = 0;
    if (scanf("%d %d", n, m) == 2 && *n > 0 && *n == *m) {
        *matrix = allocate_matrix(*n, *m);
        for (int i = 0; i < *n && exit_status == 0; i++) {
            for (int j = 0; j < *m && exit_status == 0; j++) {
                if (scanf("%lf", (*matrix)[i] + j) != 1) exit_status = -1;
            }
        }
        exit_status += check_string();
        if (exit_status != 0) free(*matrix);
    } else
        exit_status = -1;
    return exit_status;
}

void output(double **matrix, int n, int m) {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m - 1; j++) {
            printf("%.6lf ", matrix[i][j]);
        }
        if (m > 0) printf("%.6lf", matrix[i][m - 1]);
        if (i < n - 1) puts("");
    }
}

我try 使用DEBUG来查看哪里出了问题,但它告诉我,在allocate_matrix()中,从result中的transpose()调用的函数初始化Malloc中止.我不明白为什么它不像内部错误那样返回NULL,而是中止所有程序.

推荐答案

您在使用matrix_for_det函数时遇到了问题,因为它访问超出界限的res.您在错误的位置初始化了jn,因此jn将继续增加,远远超过m-1的限制.

已修复:

void matrix_for_det(double **matrix, int n, int m, double **res, int y, int x) {
    int in = 0;                          // don't initialize `jn`  here
    for (int i = 0; i < n; i++) {
        if (i == y) continue;
        int jn = 0;                      // initialize `jn` here
        for (int j = 0; j < m; j++) {
            if (j == x) continue;
            res[in][jn] = matrix[i][j];
            jn++;
        }
        in++;
    }
}

...或者在for个循环init-clauses中进行初始化.

void matrix_for_det(double **matrix, int n, int m, double **res, int y, int x) {
    for (int i = 0, in = 0; i < n; i++) {
        if (i == y) continue;
        for (int j = 0, jn = 0; j < m; j++) {
            if (j == x) continue;
            res[in][jn] = matrix[i][j];
            jn++;
        }
        in++;
    }
}

C++相关问答推荐

如何启用ss(另一个调查套接字的实用程序)来查看Linux主机上加入的多播组IP地址?

常数函数指针优化

当main函数调用被重构时,C函数给出错误的结果

如何在IF语句中正确使用0.0

为什么内核使用扩展到前后相同的宏定义?

当我运行/调试C程序时,Malloc()似乎正在将&q;r\r...&q;赋值给一个指针,我不确定为什么?

解决S随机内存分配问题,实现跨进程高效数据共享

等同于铁 rust 的纯C语言S未实现!()宏

C代码在字符串中删除不区分大小写的子字符串的问题

获取前2个连续1比特的索引的有效方法

是否定义了此函数的行为?

错误...的多个定义(&Q)首先在这里定义&

为什么这个分配做得不好呢?

如何在VSCode中创建和使用我自己的C库?

Zlib:解压缩大文件导致";无效代码长度设置";错误

与外部SPI闪存通信时是否应禁用中断?

为什么这个代码的最后一次迭代不能正常工作?

10 个字节对于这个 C 程序返回后跳行的能力有什么意义

我该如何处理这个 C 90 代码中的内存泄漏?

计算 e^x 很好.但不是 x 的罪