【问题标题】:Trying to understand the problems in my code试图理解我的代码中的问题
【发布时间】:2020-09-10 04:03:37
【问题描述】:

我正在尝试执行以下操作:

• 从用户那里接收 3 个整数:size1、size2、size3。

• 创建一个 size1 * size2 矩阵和一个 size2 * size3 矩阵。

• 将 2 个矩阵相乘。

• 打印结果矩阵。

• 释放所有动态内存。

BUT 在输入两个矩阵之后,我希望程序显示矩阵的乘法,但它会在 FreeMatrix 函数中导致断点,并如下所示: 在 Project8.exe 中的 0x0F82AC1D (ucrtbased.dll) 处引发异常:0xC0000005:访问冲突读取位置 0xCCCCCCC4。

代码:

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

void BuildMatrix(int*** pMat, int row, int col);
void FreeMatrix(int*** matrix, int row);
void PrintMatrix(int** pMat, int row, int col);
int** MultiplyMatrixes(int** a, int** b, int size1, int size2, int size3);

int main() {
    int** matrix1 = NULL, ** matrix2 = NULL, ** matrix3 = NULL;
    int* newCol = NULL;
    int size1, size2, size3, newRow;

    printf("-How many rows in the first matrix?: ");
    scanf("%d", &size1);
    printf("-How many columns in the first matrix and rows in the second matrix?[size2, size3]: ");
    scanf("%d", &size2);  /*size2 = rows of matrix2.*/
    printf("-How many columns in the second matrix?: ");
    scanf("%d", &size3);

    /*Build both matrices*/
    printf("-First matrix input.\n");
    BuildMatrix(&matrix1, size1, size2);
    PrintMatrix(matrix1, size1, size2);
    printf("-Second matrix input.\n");
    BuildMatrix(&matrix2, size2, size3);
    PrintMatrix(matrix2, size2, size3);

    /*Combine the 2 matrices to a new matrix*/
    matrix3 = MultiplyMatrixes(matrix1, matrix2, size1, size2, size3);
    FreeMatrix(&matrix2, size2); //Free the second matrix

    printf("\n-Multiplied matrix: \n");
    PrintMatrix(matrix3, size1, size3);

    FreeMatrix(&matrix3, size1);
    FreeMatrix(&matrix1, size1);
}

void BuildMatrix(int*** pMat, int row, int col) 
{
    int i, j;
    (*pMat) = (int**)malloc(row * sizeof(int*));
    if (*pMat == NULL) 
    {
        free(pMat);
        printf("*Not enough RAM.\nTerminating.\n");
        exit(1);
    }

    for (i = 0; i < row; i++) 
    {
        (*pMat)[i] = malloc(col * sizeof(int));
        if ((*pMat)[i] == NULL) {
            printf("*Not enough RAM.\nTerminating.\n");
            FreeMatrix(pMat, row);
            exit(1);
        }
        for (j = 0; j < col; j++) {
            printf("-Enter %d element in %d row: ", j + 1, i + 1);
            scanf("%d", &(*pMat)[i][j]);
        }
        printf("\n");
    }
    //FreeMatrix(pMat, row);
}

void FreeMatrix(int*** matrix, int row)
{
    for (int i = 0; i < row; i++)
    {
        free((matrix)[i]);
    }
    free(matrix);
}

void PrintMatrix(int** pMat, int row, int col) 
{
    for (int i = 0; i < row; ++i) 
    {
        for (int j = 0; j < col; ++j) 
        {
            printf("%d ", (pMat[i][j]));
        }
        printf("\n");
    }
}

int** MultiplyMatrixes(int** a, int** b, int size1, int size2, int size3)
{
    int i, j, k, ** c = NULL;
    c = (int**)malloc(size1 * sizeof(int*));
    if (c == NULL) 
    {
        free(*c);
        printf("*Not enough RAM.\nTerminating.\n");
        exit(1);
    }

    for (i = 0; i < size1; i++) {
        c[i] = malloc(size3 * sizeof(int));
        if (c[i] == NULL) 
        {
            printf("*Not enough RAM.\nTerminating.\n");
            FreeMatrix(&c, size1);
            exit(1);
        }

        for (j = 0; j < size3; j++) 
        {
            c[i][j] = 0;
            for (k = 0; k < size2; k++) 
            {
                c[i][j] += (a[i][k] * b[k][j]);
            }
        }
    }
}

【问题讨论】:

    标签: c visual-studio matrix compiler-errors breakpoints


    【解决方案1】:

    当你在BuildMatrix中分配矩阵时:

    (*pMat) = (int**)malloc(row * sizeof(int*));
    
    for (i = 0; i < row; i++) 
    {
        (*pMat)[i] = malloc(col * sizeof(int));
        ...
    }
    

    因此,在FreeMatrix 中,您的代码应更改为:

    void FreeMatrix(int*** matrix, int row)
    {
        for (int i = 0; i < row; i++)
        {
            free((*matrix)[i]); // using *matrix instead of matrix
        }
        free(*matrix); // using *matrix instead of matrix also
    }
    

    您还忘记了返回 MultiplyMatrixes 函数的值。它应该在函数末尾返回矩阵c

    您不需要释放 NULL 指针,因为如果指针为 NULL,则不会执行任何操作,例如,在您的代码中:

       (*pMat) = (int**)malloc(row * sizeof(int*));
        if (*pMat == NULL) 
        {
            free(pMat); // it's not necessary 
            printf("*Not enough RAM.\nTerminating.\n");
            exit(1);
        }
    

    【讨论】:

      【解决方案2】:

      这段代码有两个问题。 第一个问题,这会导致您在 FreeMatrix 函数中出现异常: 你传递了int***,但你没有取消引用第一个指针。

      void FreeMatrix(int*** matrix, int row)
      {
          for (int i = 0; i < row; i++)
          {
              free((matrix)[i]); // Type inside free is int**, not int*
          }
          free(matrix); // Type inside free is int***, not int**
      }
      

      应该是:

      void FreeMatrix(int*** matrix, int row)
      {
          for (int i = 0; i < row; i++)
          {
              free((*matrix)[i]); // Type inside free is int*
          }
          free(*matrix); // Type inside free is int**
      }
      

      在我修复这个问题之后,我在你的代码中遇到了matrix3 值的问题。 您在 MultiplyMatrixes 函数中缺少 return 语句和未分配的 matrix3 变量。

      应该是:

      int** MultiplyMatrixes(int** a, int** b, int size1, int size2, int size3)
      {
          int i, j, k, ** c = NULL;
          c = (int**)malloc(size1 * sizeof(int*));
          if (c == NULL)
          {
              free(*c);
              printf("*Not enough RAM.\nTerminating.\n");
              exit(1);
          }
      
          for (i = 0; i < size1; i++) {
              c[i] = malloc(size3 * sizeof(int));
              if (c[i] == NULL)
              {
                  printf("*Not enough RAM.\nTerminating.\n");
                  FreeMatrix(&c, size1);
                  exit(1);
              }
      
              for (j = 0; j < size3; j++)
              {
                  c[i][j] = 0;
                  for (k = 0; k < size2; k++)
                  {
                      c[i][j] += (a[i][k] * b[k][j]);
                  }
              }
          }
      
          return c; // <====
      }
      

      另外我建议您将矩阵分配为指针行和连续数组。 像这样:

      int** matrix = (int*)malloc(sizeof(int*) * rows); // pointers to rows
      matrix[0] = (int*)malloc(rows * cols); // single chunk of memory for all elems
      for(int i = 0; i < rows; ++i)
          matrix[i] = matrix[0] + i * cols;
      

      元素访问:

      elem = matrix[row_index][col_index];
      

      释放:

      if (rows)
         free(matrix[0]);
      free(matrix);
      

      另一种选择是将矩阵分配为连续数组。

      像这样:

      int** matrix = (int*)malloc(sizeof(int*) * cols * rows); // single chunk of memory for all elems
      

      元素访问:

      elem = matrix[row_index * row_size + col_index];
      

      在这种方法中,解除分配更加简单:

      if(matrix)
         free(matrix);
      

      作为一个简单的内存块分配简化了内存释放,这样的代码对缓存更加友好。

      【讨论】:

        【解决方案3】:

        这是修改后的工作代码。
        基本上,乘法函数没有返回分配的地址
        并且与三重指针 pMat 不匹配。
        此外,在处理错误分配的内存时应该更加小心。
        只需将您的代码与我的代码并排比较即可。
        我尝试添加有用的 cmets。

        #include <stdlib.h>
        #include <stdio.h>
        
        void BuildMatrix(int*** pMat, int row, int col);
        void FreeMatrix(int*** matrix, int row);
        void PrintMatrix(int** pMat, int row, int col);
        int** MultiplyMatrixes(int** a, int** b, int size1, int size2, int size3);
        
        int main() {
            int** matrix1 = NULL, ** matrix2 = NULL, ** matrix3 = NULL;
            int* newCol = NULL;
            int size1, size2, size3, newRow;
        
            printf("-How many rows in the first matrix?: ");
            scanf("%d", &size1);
            printf("-How many columns in the first matrix and rows in the second matrix?[size2, size3]: ");
            scanf("%d", &size2);  /*size2 = rows of matrix2.*/
            printf("-How many columns in the second matrix?: ");
            scanf("%d", &size3);
        
            /*Build both matrices*/
            printf("-First matrix input.\n");
            BuildMatrix(&matrix1, size1, size2);
            PrintMatrix(matrix1, size1, size2);
            printf("-Second matrix input.\n");
            BuildMatrix(&matrix2, size2, size3);
            PrintMatrix(matrix2, size2, size3);
        
            /*Combine the 2 matrices to a new matrix*/
            matrix3 = MultiplyMatrixes(matrix1, matrix2, size1, size2, size3);
            FreeMatrix(&matrix2, size2); //Free the second matrix
        
            printf("\n-Multiplied matrix: \n");
            PrintMatrix(matrix3, size1, size3);
        
            FreeMatrix(&matrix3, size1);
            FreeMatrix(&matrix1, size1);
        }
        
        void BuildMatrix(int*** pMat, int row, int col) 
        {
            int i, j;
            (*pMat) = (int**)malloc(row * sizeof(int*));
            if (*pMat == NULL) 
            {
                // pMat is a pointer to the "whole" matrix and mirrors
                // the calling parameter matrix1, e.g. So always use it dereferenced.
                // If *pMat is NULL there is nothing to free (at NULL).
                //free(*pMat);
                printf("*Not enough RAM.\nTerminating.\n");
                exit(1);
            }
        
            for (i = 0; i < row; i++) 
            {
                (*pMat)[i] = malloc(col * sizeof(int));
                //if(i == 1) //to try exception handling code
                if ((*pMat)[i] == NULL) 
                {
                    int d;
                    printf("*Not enough RAM.\nTerminating.\n");
                    //FreeMatrix(pMat, row);
                // Your new matrix isn't complete so you should free *pMat here, 
                // and free (*pMat)[?] with ? from 0 to i-1 
                    for (d = 0; d < i; ++d) free((*pMat)[d]); free(*pMat);
                    exit(1);
                }
                for (j = 0; j < col; j++) {
                    printf("-Enter %d element in %d row: ", j + 1, i + 1);
                    scanf("%d", &(*pMat)[i][j]);
                }
                printf("\n");
            }
            //FreeMatrix(pMat, row);
        }
        
        void FreeMatrix(int*** matrix, int row)
        {
            for (int i = 0; i < row; i++)
            {
                // pMat is a pointer to the "whole" matrix and mirrors
                // the calling parameter matrix1, e.g. So always use it dereferenced.
                free((*matrix)[i]);
            }
            free(*matrix);
        }
        
        void PrintMatrix(int** pMat, int row, int col) 
        {
            for (int i = 0; i < row; ++i) 
            {
                for (int j = 0; j < col; ++j) 
                {
                    printf("%d ", (pMat[i][j]));
                }
                printf("\n");
            }
        }
        
        int** MultiplyMatrixes(int** a, int** b, int size1, int size2, int size3)
        {
            int i, j, k, ** c = NULL;
            c = (int**)malloc(size1 * sizeof(int*));
            if (c == NULL) 
            {
                // If c is NULL there is nothing to free (at NULL).
                //free(c);
                printf("*Not enough RAM.\nTerminating.\n");
                exit(1);
            }
        
            for (i = 0; i < size1; i++) {
                c[i] = malloc(size3 * sizeof(int));
                //if(i == 1) //to try exception handling code
                if (c[i] == NULL) 
                {
                    int d;
                    printf("*Not enough RAM.\nTerminating.\n");
                    //FreeMatrix(&c, size1);
                // Your new matrix isn't complete so you should free c here, 
                // and free c[?] with ? from 0 to i-1   
                    for (d =0; d < i; ++d) free(c[d]); free(c);
                    exit(1);
                }
        
                for (j = 0; j < size3; j++) 
                {
                    c[i][j] = 0;
                    for (k = 0; k < size2; k++) 
                    {
                        c[i][j] += (a[i][k] * b[k][j]);
                    }
                }
            }
            return c;
        }
        

        【讨论】:

          猜你喜欢
          • 2011-03-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-02-25
          • 1970-01-01
          • 2020-08-13
          • 2014-07-01
          • 1970-01-01
          相关资源
          最近更新 更多