更改宏值时出现段错误

时间:2018-09-21 10:16:12

标签: c multidimensional-array segmentation-fault

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>

#define len 10
#define hi 10

void transpose(double (*matrix)[len][hi]);

int main() {
  srand(time(NULL));
  double (*matrix)[len][hi] = (double (*)[len][hi])malloc(sizeof(double[len][hi]));
  double delimo, delitel;
  for(int i = 0; i < len; i++){
    for(int j = 0; j < hi; j++){
      delimo = rand()%(len * hi);
      delitel = rand()%(len * hi);
      *matrix[i][j] = delimo/++delitel;
      printf(" %5.2lf ", *matrix[i][j]);
    }
    puts("");
  }
  puts("Transpose: ");
    transpose(matrix);
    for(int i = 0; i < len; i++){
      for(int j = 0; j < hi; j++){
        printf(" %5.2lf ", *matrix[i][j]);
      }
      puts("");
    }
   free(matrix);

}

void transpose(double (*matrix)[len][hi]){
  double (*Tmatrix)[len][hi] = (double (*)[len][hi])malloc(sizeof(double[len][hi]));
  for(int i = 0; i < len; i++){
    for(int j = 0; j < hi; j++){
      *Tmatrix[i][j] = *matrix[j][i];
    }
  }
  for(int i = 0; i < len; i++){
    for(int j = 0; j < hi; j++){
      *matrix[i][j] = *Tmatrix[i][j];
    }
  }
  free(Tmatrix);
}

任务是分配一个2d数组,然后让一个函数对其进行转置,并通过一个函数调用将转置后的矩阵复制到原始数组中。矩阵的尺寸由宏设置,并且还可以在几个循环中以及分配2个矩阵时使用。但是出于某种奇怪的原因,如果我决定更改它们,则会出现段错误。只有永不崩溃的是len = hi = 10。在任何其他情况下,程序平均有超过平均崩溃的机会。

3 个答案:

答案 0 :(得分:1)

您正尝试在原位置转置矩阵 ,这是有问题的。实际上,转置非正方形矩阵会得到不同维度的矩阵。因此,由于您试图将转置的矩阵放入不正确尺寸的数组中,因此会无意间将数据写入不应访问的内存中。

我建议您修改转置函数,使其以两个矩阵为参数。第一个是要转置的矩阵,第二个是接收转置矩阵的矩阵,它的尺寸正确。

答案 1 :(得分:1)

问题中显示的代码为我构建了Valgrind组合,因为它没有正确使用指针矩阵表示法。当独立运行时(不是在Valgrind下运行),它似乎可以工作,但是输出矩阵不是输入矩阵的转置-因为尚未正确访问数据。这是我得到的虚假输出的一个示例。您可以看到“转置”矩阵中索引为0,1和1,0的元素与原始矩阵中的元素无关。

  1.24   2.64   0.17   0.49  22.25   4.30   0.71   1.12   1.03   2.31 
  1.39   7.18   0.40   0.44   4.30   0.17   0.62  12.67   0.34   9.10 
  2.85   0.69   3.50   1.58   0.77   0.04   0.26   0.79   0.24   1.59 
 16.00   0.14   0.12   0.56   1.68   0.08   0.69   0.13   2.51   1.74 
  5.50   0.96   0.45   1.00   0.00   0.84   0.97   0.40   2.14   0.67 
  2.00   0.14   1.84   0.88   1.26   0.21   0.70   0.30   1.74   0.60 
  2.04   1.00   0.35   0.12   0.00   0.65   1.21   0.18   0.52   9.70 
  1.19   1.08   0.88   1.71   0.88   0.21   1.74   0.70   0.44   1.23 
  1.38   0.69   0.12   0.14   4.18   3.17   0.06   7.10   8.00   1.52 
  0.16   6.07   0.81   0.49   0.14   1.37   4.00   0.93   0.98   1.48 
Transpose: 
  1.24   1.24   2.64   0.17   0.49  22.25   4.30   0.71   1.12   1.03 
 -2.00   1.39   1.39   2.85  16.00   5.50   2.00   2.04   1.19   1.38 
  0.17   2.85   0.69   0.69   0.14   0.96   0.14   1.00   1.08   0.69 
  0.49  16.00   0.14   0.12   0.12   0.45   1.84   0.35   0.88   0.12 
 22.25   5.50   0.96   0.45   1.00   1.00   0.88   0.12   1.71   0.14 
  4.30   2.00   0.14   1.84   0.88   1.26   1.26   0.00   0.88   4.18 
  0.71   2.04   1.00   0.35   0.12   0.00   0.65   0.65   0.21   3.17 
  1.12   1.19   1.08   0.88   1.71   0.88   0.21   1.74   1.74   0.06 
  1.03   1.38   0.69   0.12   0.14   4.18   3.17   0.06   7.10   7.10 
  2.31   0.16   6.07   0.81   0.49   0.14   1.37   4.00   0.93   0.98 

下面的代码适用于平方矩阵。区别在于,在应用下标((*matrix)[i][j])之前而不是在{*matrix[i][j])之后取消了指向矩阵的指针。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define len 10
#define hi 10

void transpose(double (*matrix)[len][hi]);

int main(void)
{
    srand(time(NULL));
    double (*matrix)[len][hi] = (double (*)[len][hi])malloc(sizeof(double[len][hi]));
    double delimo, delitel;
    for (int i = 0; i < len; i++)
    {
        for (int j = 0; j < hi; j++)
        {
            delimo = rand() % (len * hi);
            delitel = rand() % (len * hi);
            (*matrix)[i][j] = delimo / ++delitel;
            printf(" %5.2lf ", (*matrix)[i][j]);
        }
        puts("");
    }
    puts("Transpose: ");
    transpose(matrix);
    for (int i = 0; i < len; i++)
    {
        for (int j = 0; j < hi; j++)
        {
            printf(" %5.2lf ", (*matrix)[i][j]);
        }
        puts("");
    }
    free(matrix);
}

void transpose(double (*matrix)[len][hi])
{
    double (*Tmatrix)[len][hi] = (double (*)[len][hi])malloc(sizeof(double[len][hi]));
    for (int i = 0; i < len; i++)
    {
        for (int j = 0; j < hi; j++)
        {
            (*Tmatrix)[i][j] = (*matrix)[j][i];
        }
    }
    for (int i = 0; i < len; i++)
    {
        for (int j = 0; j < hi; j++)
        {
            (*matrix)[i][j] = (*Tmatrix)[i][j];
        }
    }
    free(Tmatrix);
}

示例输出:

  0.98   0.90   0.16   0.08   0.48   1.71   0.53   0.24   2.28   1.79 
  0.73   0.36   2.00   3.27   0.29   1.25  19.40   1.60   0.56   0.00 
  3.00  10.50   1.81   1.56   1.11   0.78   1.53   0.71   1.27   0.93 
  2.10   0.56   2.34   1.48   0.81   2.16   0.47   0.16   7.62   0.91 
  0.93   2.48   0.15   0.71   1.09   0.73   0.58   0.48   1.13   0.99 
  0.59   0.72   8.75   2.19  61.00   1.41   2.08   0.83   0.65   0.16 
  0.42   1.13   0.85   1.00   3.00   0.55   0.33   1.67   0.44   0.69 
  0.08   1.17   0.25   0.92   1.04   0.17   1.77   1.95   0.50   0.90 
  2.28   0.35   0.41   1.27   0.80   3.36   0.29   0.13   3.88   0.39 
  0.64   0.50   0.40   0.15   0.45   0.78   0.31   1.48   1.50   1.06 
Transpose: 
  0.98   0.73   3.00   2.10   0.93   0.59   0.42   0.08   2.28   0.64 
  0.90   0.36  10.50   0.56   2.48   0.72   1.13   1.17   0.35   0.50 
  0.16   2.00   1.81   2.34   0.15   8.75   0.85   0.25   0.41   0.40 
  0.08   3.27   1.56   1.48   0.71   2.19   1.00   0.92   1.27   0.15 
  0.48   0.29   1.11   0.81   1.09  61.00   3.00   1.04   0.80   0.45 
  1.71   1.25   0.78   2.16   0.73   1.41   0.55   0.17   3.36   0.78 
  0.53  19.40   1.53   0.47   0.58   2.08   0.33   1.77   0.29   0.31 
  0.24   1.60   0.71   0.16   0.48   0.83   1.67   1.95   0.13   1.48 
  2.28   0.56   1.27   7.62   1.13   0.65   0.44   0.50   3.88   1.50 
  1.79   0.00   0.93   0.91   0.99   0.16   0.69   0.90   0.39   1.06 

您不能原位转置非正方形矩阵。如果您有一个n x m矩阵作为输入,则转置为m x n矩阵。在您分配非转置的地方分配转置矩阵,然后将两个矩阵都传递给转置函数,这可能是最简单的。请注意,使用*matrix可以将指向矩阵的指针作为矩阵传递给函数。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

void transpose(int rows, int cols, double matrix[rows][cols], double result[cols][rows]);
void print_matrix(const char *tag, int rows, int cols, double matrix[rows][cols]);

int main(void)
{
    srand(time(NULL));
    int cols = 10;
    int rows =  8;
    double (*matrix)[rows][cols] = malloc(sizeof(double[rows][cols]));
    double (*result)[cols][rows] = malloc(sizeof(double[cols][rows]));
    if (matrix == 0 || result == 0)
    {
        fprintf(stderr, "failed to allocate memory\n");
        exit(EXIT_FAILURE);
    }

    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            double delimo = rand() % (rows * cols);
            double delitel = rand() % (rows * cols) + 1;
            (*matrix)[i][j] = delimo / delitel;
        }
    }

    print_matrix("original", rows, cols, *matrix);
    transpose(rows, cols, *matrix, *result);
    print_matrix("transpose", cols, rows, *result);

    free(matrix);
    free(result);
    return 0;
}

void print_matrix(const char *tag, int rows, int cols, double matrix[rows][cols])
{
    printf("%s (%dx%d):\n", tag, rows, cols);
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
            printf(" %5.2f ", matrix[i][j]);
        putchar('\n');
    }
}

void transpose(int rows, int cols, double matrix[rows][cols], double result[cols][rows])
{
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            result[j][i] = matrix[i][j];
        }
    }
}

示例输出:

original (8x10):
  0.84   0.92   0.18   1.97   4.54  31.00   1.59   0.11   0.35   0.07 
  0.96   3.19   1.00   4.86   3.25   3.50   2.65   1.07   0.24   0.77 
  6.00   0.13   0.40   1.04   0.99   0.88   1.24   0.67   3.07  12.00 
  1.89   0.48   0.72   0.55   0.26   0.64   0.55   0.09   0.30   0.98 
  0.51   0.86   0.85   0.33   1.44   0.89   2.38   2.21   0.27   2.12 
  6.40   1.71   2.83   1.61   0.76   0.13   0.81   1.48   1.13   0.51 
  0.79   0.69   0.57   1.10   1.00   1.31   0.68   1.95   1.42   0.46 
  0.00   0.43   1.64   0.88   1.03   0.14   0.35   1.78   0.86   2.82 
transpose (10x8):
  0.84   0.96   6.00   1.89   0.51   6.40   0.79   0.00 
  0.92   3.19   0.13   0.48   0.86   1.71   0.69   0.43 
  0.18   1.00   0.40   0.72   0.85   2.83   0.57   1.64 
  1.97   4.86   1.04   0.55   0.33   1.61   1.10   0.88 
  4.54   3.25   0.99   0.26   1.44   0.76   1.00   1.03 
 31.00   3.50   0.88   0.64   0.89   0.13   1.31   0.14 
  1.59   2.65   1.24   0.55   2.38   0.81   0.68   0.35 
  0.11   1.07   0.67   0.09   2.21   1.48   1.95   1.78 
  0.35   0.24   3.07   0.30   0.27   1.13   1.42   0.86 
  0.07   0.77  12.00   0.98   2.12   0.51   0.46   2.82 

Valgrind为这两者提供了清晰的健康清单。原始代码导致Valgrind报告许多错误,例如:

==33404== Signal 11 being dropped from thread 0's queue

我不得不终止从另一个终端窗口运行的程序。

答案 2 :(得分:-1)

您太努力了。只需删除所有动态分配内容以及指针。在您的情况下,动态内存分配完全没有用。

您在这里:

#define len 2
#define hi 2

void transpose(double matrix[len][hi]);

int main() {
  srand(time(NULL));
  double matrix[len][hi];
  double delimo, delitel;
  for (int i = 0; i < len; i++) {
    for (int j = 0; j < hi; j++) {
      delimo = rand() % (len * hi);
      delitel = rand() % (len * hi);
      matrix[i][j] = delimo / ++delitel;
      printf(" %5.2lf ", matrix[i][j]);
    }
    puts("");
  }
  puts("Transpose: ");
  transpose(matrix);
  for (int i = 0; i < len; i++) {
    for (int j = 0; j < hi; j++) {
      printf(" %5.2lf ", matrix[i][j]);
    }
    puts("");
  }
}

void transpose (double matrix[len][hi]) {
  double Tmatrix[len][hi];
  for (int i = 0; i < len; i++) {
    for (int j = 0; j < hi; j++) {
      Tmatrix[i][j] = matrix[j][i];
    }
  }
  for (int i = 0; i < len; i++) {
    for (int j = 0; j < hi; j++) {
      matrix[i][j] = Tmatrix[i][j];
    }
  }
}

免责声明:

  • 这仅适用于方阵。
  • 可能还有其他问题